From 0205e530afc8263a9b5f818e3a566d50d5965781 Mon Sep 17 00:00:00 2001 From: Igor Pecovnik Date: Thu, 16 May 2019 12:17:37 +0200 Subject: [PATCH] [ sunxi-next ] upstream patches --- .../kernel/sunxi-next/patch-4.19.38-39.patch | 2295 ++++++++ .../kernel/sunxi-next/patch-4.19.39-40.patch | 1032 ++++ .../kernel/sunxi-next/patch-4.19.40-41.patch | 3563 +++++++++++++ .../kernel/sunxi-next/patch-4.19.41-42.patch | 4659 +++++++++++++++++ .../kernel/sunxi-next/patch-4.19.42-43.patch | 3611 +++++++++++++ .../sunxi-next/xxx-opi-win-bluetooth.patch | 56 + 6 files changed, 15216 insertions(+) create mode 100644 patch/kernel/sunxi-next/patch-4.19.38-39.patch create mode 100644 patch/kernel/sunxi-next/patch-4.19.39-40.patch create mode 100644 patch/kernel/sunxi-next/patch-4.19.40-41.patch create mode 100644 patch/kernel/sunxi-next/patch-4.19.41-42.patch create mode 100644 patch/kernel/sunxi-next/patch-4.19.42-43.patch create mode 100644 patch/kernel/sunxi-next/xxx-opi-win-bluetooth.patch diff --git a/patch/kernel/sunxi-next/patch-4.19.38-39.patch b/patch/kernel/sunxi-next/patch-4.19.38-39.patch new file mode 100644 index 0000000000..489af445cb --- /dev/null +++ b/patch/kernel/sunxi-next/patch-4.19.38-39.patch @@ -0,0 +1,2295 @@ +diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 +index d1ee484a787d..ee9984f35868 100644 +--- a/Documentation/i2c/busses/i2c-i801 ++++ b/Documentation/i2c/busses/i2c-i801 +@@ -36,6 +36,7 @@ Supported adapters: + * Intel Cannon Lake (PCH) + * Intel Cedar Fork (PCH) + * Intel Ice Lake (PCH) ++ * Intel Comet Lake (PCH) + Datasheets: Publicly available at the Intel website + + On Intel Patsburg and later chipsets, both the normal host SMBus controller +diff --git a/Makefile b/Makefile +index 14d4aeb48907..be1bd297bca9 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 4 + PATCHLEVEL = 19 +-SUBLEVEL = 38 ++SUBLEVEL = 39 + EXTRAVERSION = + NAME = "People's Front" + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index cd4c74daf71e..51794c7fa6d5 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -612,6 +612,7 @@ config ARCH_DAVINCI + select HAVE_IDE + select PM_GENERIC_DOMAINS if PM + select PM_GENERIC_DOMAINS_OF if PM && OF ++ select REGMAP_MMIO + select RESET_CONTROLLER + select USE_OF + select ZONE_DMA +diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts +index 5641d162dfdb..28e7513ce617 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts ++++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts +@@ -93,7 +93,7 @@ + }; + + &hdmi { +- hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; ++ hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; + }; + + &pwm { +diff --git a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi b/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi +index acc3b11fba2a..cde3025d9603 100644 +--- a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi +@@ -298,7 +298,7 @@ + pinctrl-2 = <&pinctrl_usdhc3_200mhz>; + vmcc-supply = <®_sd3_vmmc>; + cd-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; +- bus-witdh = <4>; ++ bus-width = <4>; + no-1-8-v; + status = "okay"; + }; +@@ -309,7 +309,7 @@ + pinctrl-1 = <&pinctrl_usdhc4_100mhz>; + pinctrl-2 = <&pinctrl_usdhc4_200mhz>; + vmcc-supply = <®_sd4_vmmc>; +- bus-witdh = <8>; ++ bus-width = <8>; + no-1-8-v; + non-removable; + status = "okay"; +diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi +index ed1aafd56973..fe4e89d773f5 100644 +--- a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi +@@ -89,6 +89,7 @@ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; ++ phy-reset-duration = <10>; /* in msecs */ + phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>; + phy-supply = <&vdd_eth_io_reg>; + status = "disabled"; +diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h +index 265ea9cf7df7..523c499e42db 100644 +--- a/arch/arm/include/asm/kvm_mmu.h ++++ b/arch/arm/include/asm/kvm_mmu.h +@@ -317,6 +317,17 @@ static inline int kvm_read_guest_lock(struct kvm *kvm, + return ret; + } + ++static inline int kvm_write_guest_lock(struct kvm *kvm, gpa_t gpa, ++ const void *data, unsigned long len) ++{ ++ int srcu_idx = srcu_read_lock(&kvm->srcu); ++ int ret = kvm_write_guest(kvm, gpa, data, len); ++ ++ srcu_read_unlock(&kvm->srcu, srcu_idx); ++ ++ return ret; ++} ++ + static inline void *kvm_get_hyp_vector(void) + { + switch(read_cpuid_part()) { +diff --git a/arch/arm/mach-imx/mach-imx51.c b/arch/arm/mach-imx/mach-imx51.c +index c7169c2f94c4..08c7892866c2 100644 +--- a/arch/arm/mach-imx/mach-imx51.c ++++ b/arch/arm/mach-imx/mach-imx51.c +@@ -59,6 +59,7 @@ static void __init imx51_m4if_setup(void) + return; + + m4if_base = of_iomap(np, 0); ++ of_node_put(np); + if (!m4if_base) { + pr_err("Unable to map M4IF registers\n"); + return; +diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h +index d6fff7de5539..b2558447c67d 100644 +--- a/arch/arm64/include/asm/kvm_mmu.h ++++ b/arch/arm64/include/asm/kvm_mmu.h +@@ -394,6 +394,17 @@ static inline int kvm_read_guest_lock(struct kvm *kvm, + return ret; + } + ++static inline int kvm_write_guest_lock(struct kvm *kvm, gpa_t gpa, ++ const void *data, unsigned long len) ++{ ++ int srcu_idx = srcu_read_lock(&kvm->srcu); ++ int ret = kvm_write_guest(kvm, gpa, data, len); ++ ++ srcu_read_unlock(&kvm->srcu, srcu_idx); ++ ++ return ret; ++} ++ + #ifdef CONFIG_KVM_INDIRECT_VECTORS + /* + * EL2 vectors can be mapped and rerouted in a number of ways, +diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c +index 18b9a522a2b3..0688816f19e2 100644 +--- a/arch/arm64/kvm/reset.c ++++ b/arch/arm64/kvm/reset.c +@@ -117,6 +117,9 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) + int ret = -EINVAL; + bool loaded; + ++ /* Reset PMU outside of the non-preemptible section */ ++ kvm_pmu_vcpu_reset(vcpu); ++ + preempt_disable(); + loaded = (vcpu->cpu != -1); + if (loaded) +@@ -164,9 +167,6 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) + vcpu->arch.reset_state.reset = false; + } + +- /* Reset PMU */ +- kvm_pmu_vcpu_reset(vcpu); +- + /* Default workaround setup is enabled (if supported) */ + if (kvm_arm_have_ssbd() == KVM_SSBD_KERNEL) + vcpu->arch.workaround_flags |= VCPU_WORKAROUND_2_FLAG; +diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h +index 7d22a474a040..f74639a05f0f 100644 +--- a/arch/s390/include/asm/elf.h ++++ b/arch/s390/include/asm/elf.h +@@ -252,11 +252,14 @@ do { \ + + /* + * Cache aliasing on the latest machines calls for a mapping granularity +- * of 512KB. For 64-bit processes use a 512KB alignment and a randomization +- * of up to 1GB. For 31-bit processes the virtual address space is limited, +- * use no alignment and limit the randomization to 8MB. ++ * of 512KB for the anonymous mapping base. For 64-bit processes use a ++ * 512KB alignment and a randomization of up to 1GB. For 31-bit processes ++ * the virtual address space is limited, use no alignment and limit the ++ * randomization to 8MB. ++ * For the additional randomization of the program break use 32MB for ++ * 64-bit and 8MB for 31-bit. + */ +-#define BRK_RND_MASK (is_compat_task() ? 0x7ffUL : 0x3ffffUL) ++#define BRK_RND_MASK (is_compat_task() ? 0x7ffUL : 0x1fffUL) + #define MMAP_RND_MASK (is_compat_task() ? 0x7ffUL : 0x3ff80UL) + #define MMAP_ALIGN_MASK (is_compat_task() ? 0 : 0x7fUL) + #define STACK_RND_MASK MMAP_RND_MASK +diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c +index 1e95d57760cf..b69f7d428443 100644 +--- a/arch/x86/mm/mmap.c ++++ b/arch/x86/mm/mmap.c +@@ -230,7 +230,7 @@ bool mmap_address_hint_valid(unsigned long addr, unsigned long len) + /* Can we access it for direct reading/writing? Must be RAM: */ + int valid_phys_addr_range(phys_addr_t addr, size_t count) + { +- return addr + count <= __pa(high_memory); ++ return addr + count - 1 <= __pa(high_memory - 1); + } + + /* Can we access it through mmap? Must be a valid physical address: */ +diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c +index d10105825d57..47d097946872 100644 +--- a/arch/x86/realmode/init.c ++++ b/arch/x86/realmode/init.c +@@ -20,8 +20,6 @@ void __init set_real_mode_mem(phys_addr_t mem, size_t size) + void *base = __va(mem); + + real_mode_header = (struct real_mode_header *) base; +- printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n", +- base, (unsigned long long)mem, size); + } + + void __init reserve_real_mode(void) +diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c +index 4424997ecf30..e10fec99a182 100644 +--- a/drivers/acpi/acpica/evgpe.c ++++ b/drivers/acpi/acpica/evgpe.c +@@ -81,12 +81,8 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) + + ACPI_FUNCTION_TRACE(ev_enable_gpe); + +- /* Clear the GPE status */ +- status = acpi_hw_clear_gpe(gpe_event_info); +- if (ACPI_FAILURE(status)) +- return_ACPI_STATUS(status); +- + /* Enable the requested GPE */ ++ + status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE); + return_ACPI_STATUS(status); + } +diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c +index b3ed8f9953a8..173e6f2dd9af 100644 +--- a/drivers/ata/libata-zpodd.c ++++ b/drivers/ata/libata-zpodd.c +@@ -52,38 +52,52 @@ static int eject_tray(struct ata_device *dev) + /* Per the spec, only slot type and drawer type ODD can be supported */ + static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev) + { +- char buf[16]; ++ char *buf; + unsigned int ret; +- struct rm_feature_desc *desc = (void *)(buf + 8); ++ struct rm_feature_desc *desc; + struct ata_taskfile tf; + static const char cdb[] = { GPCMD_GET_CONFIGURATION, + 2, /* only 1 feature descriptor requested */ + 0, 3, /* 3, removable medium feature */ + 0, 0, 0,/* reserved */ +- 0, sizeof(buf), ++ 0, 16, + 0, 0, 0, + }; + ++ buf = kzalloc(16, GFP_KERNEL); ++ if (!buf) ++ return ODD_MECH_TYPE_UNSUPPORTED; ++ desc = (void *)(buf + 8); ++ + ata_tf_init(dev, &tf); + tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf.command = ATA_CMD_PACKET; + tf.protocol = ATAPI_PROT_PIO; +- tf.lbam = sizeof(buf); ++ tf.lbam = 16; + + ret = ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE, +- buf, sizeof(buf), 0); +- if (ret) ++ buf, 16, 0); ++ if (ret) { ++ kfree(buf); + return ODD_MECH_TYPE_UNSUPPORTED; ++ } + +- if (be16_to_cpu(desc->feature_code) != 3) ++ if (be16_to_cpu(desc->feature_code) != 3) { ++ kfree(buf); + return ODD_MECH_TYPE_UNSUPPORTED; ++ } + +- if (desc->mech_type == 0 && desc->load == 0 && desc->eject == 1) ++ if (desc->mech_type == 0 && desc->load == 0 && desc->eject == 1) { ++ kfree(buf); + return ODD_MECH_TYPE_SLOT; +- else if (desc->mech_type == 1 && desc->load == 0 && desc->eject == 1) ++ } else if (desc->mech_type == 1 && desc->load == 0 && ++ desc->eject == 1) { ++ kfree(buf); + return ODD_MECH_TYPE_DRAWER; +- else ++ } else { ++ kfree(buf); + return ODD_MECH_TYPE_UNSUPPORTED; ++ } + } + + /* Test if ODD is zero power ready by sense code */ +diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c +index 2342e154029b..b696ec35efb3 100644 +--- a/drivers/gpio/gpio-aspeed.c ++++ b/drivers/gpio/gpio-aspeed.c +@@ -1225,6 +1225,8 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) + + gpio->offset_timer = + devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL); ++ if (!gpio->offset_timer) ++ return -ENOMEM; + + return aspeed_gpio_setup_irqs(gpio, pdev); + } +diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c +index d4e7a09598fa..e0f149bdf98f 100644 +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -646,7 +646,13 @@ int of_gpiochip_add(struct gpio_chip *chip) + + of_node_get(chip->of_node); + +- return of_gpiochip_scan_gpios(chip); ++ status = of_gpiochip_scan_gpios(chip); ++ if (status) { ++ of_node_put(chip->of_node); ++ gpiochip_remove_pin_ranges(chip); ++ } ++ ++ return status; + } + + void of_gpiochip_remove(struct gpio_chip *chip) +diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c +index ea4941da9b27..0201ccb22f4c 100644 +--- a/drivers/gpu/drm/drm_drv.c ++++ b/drivers/gpu/drm/drm_drv.c +@@ -381,11 +381,7 @@ void drm_dev_unplug(struct drm_device *dev) + synchronize_srcu(&drm_unplug_srcu); + + drm_dev_unregister(dev); +- +- mutex_lock(&drm_global_mutex); +- if (dev->open_count == 0) +- drm_dev_put(dev); +- mutex_unlock(&drm_global_mutex); ++ drm_dev_put(dev); + } + EXPORT_SYMBOL(drm_dev_unplug); + +diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c +index ffa8dc35515f..e4ccb52c67ea 100644 +--- a/drivers/gpu/drm/drm_file.c ++++ b/drivers/gpu/drm/drm_file.c +@@ -479,11 +479,9 @@ int drm_release(struct inode *inode, struct file *filp) + + drm_file_free(file_priv); + +- if (!--dev->open_count) { ++ if (!--dev->open_count) + drm_lastclose(dev); +- if (drm_dev_is_unplugged(dev)) +- drm_put_dev(dev); +- } ++ + mutex_unlock(&drm_global_mutex); + + drm_minor_release(minor); +diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c +index 611ac340fb28..588b3b0c8315 100644 +--- a/drivers/gpu/drm/meson/meson_drv.c ++++ b/drivers/gpu/drm/meson/meson_drv.c +@@ -300,10 +300,12 @@ static int meson_drv_bind_master(struct device *dev, bool has_components) + + ret = drm_dev_register(drm, 0); + if (ret) +- goto free_drm; ++ goto uninstall_irq; + + return 0; + ++uninstall_irq: ++ drm_irq_uninstall(drm); + free_drm: + drm_dev_put(drm); + +@@ -317,10 +319,11 @@ static int meson_drv_bind(struct device *dev) + + static void meson_drv_unbind(struct device *dev) + { +- struct drm_device *drm = dev_get_drvdata(dev); +- struct meson_drm *priv = drm->dev_private; ++ struct meson_drm *priv = dev_get_drvdata(dev); ++ struct drm_device *drm = priv->drm; + + drm_dev_unregister(drm); ++ drm_irq_uninstall(drm); + drm_kms_helper_poll_fini(drm); + drm_fbdev_cma_fini(priv->fbdev); + drm_mode_config_cleanup(drm); +diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c +index 8f4fcbb515fb..bb97cad1eb69 100644 +--- a/drivers/gpu/drm/tegra/hub.c ++++ b/drivers/gpu/drm/tegra/hub.c +@@ -378,14 +378,16 @@ static int tegra_shared_plane_atomic_check(struct drm_plane *plane, + static void tegra_shared_plane_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) + { +- struct tegra_dc *dc = to_tegra_dc(old_state->crtc); + struct tegra_plane *p = to_tegra_plane(plane); ++ struct tegra_dc *dc; + u32 value; + + /* rien ne va plus */ + if (!old_state || !old_state->crtc) + return; + ++ dc = to_tegra_dc(old_state->crtc); ++ + /* + * XXX Legacy helpers seem to sometimes call ->atomic_disable() even + * on planes that are already disabled. Make sure we fallback to the +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index ac4b09642f63..8f803812ea24 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -131,6 +131,7 @@ config I2C_I801 + Cannon Lake (PCH) + Cedar Fork (PCH) + Ice Lake (PCH) ++ Comet Lake (PCH) + + This driver can also be built as a module. If so, the module + will be called i2c-i801. +diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c +index c91e145ef5a5..679c6c41f64b 100644 +--- a/drivers/i2c/busses/i2c-i801.c ++++ b/drivers/i2c/busses/i2c-i801.c +@@ -71,6 +71,7 @@ + * Cannon Lake-LP (PCH) 0x9da3 32 hard yes yes yes + * Cedar Fork (PCH) 0x18df 32 hard yes yes yes + * Ice Lake-LP (PCH) 0x34a3 32 hard yes yes yes ++ * Comet Lake (PCH) 0x02a3 32 hard yes yes yes + * + * Features supported by this driver: + * Software PEC no +@@ -240,6 +241,7 @@ + #define PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS 0xa223 + #define PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS 0xa2a3 + #define PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS 0xa323 ++#define PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS 0x02a3 + + struct i801_mux_config { + char *gpio_chip; +@@ -1038,6 +1040,7 @@ static const struct pci_device_id i801_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS) }, + { 0, } + }; + +@@ -1534,6 +1537,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) + case PCI_DEVICE_ID_INTEL_DNV_SMBUS: + case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS: + case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS: ++ case PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS: + priv->features |= FEATURE_I2C_BLOCK_READ; + priv->features |= FEATURE_IRQ; + priv->features |= FEATURE_SMBUS_PEC; +diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c +index 0b3877681e4a..8d9920ff4134 100644 +--- a/drivers/iommu/amd_iommu.c ++++ b/drivers/iommu/amd_iommu.c +@@ -3119,21 +3119,24 @@ static void amd_iommu_get_resv_regions(struct device *dev, + return; + + list_for_each_entry(entry, &amd_iommu_unity_map, list) { ++ int type, prot = 0; + size_t length; +- int prot = 0; + + if (devid < entry->devid_start || devid > entry->devid_end) + continue; + ++ type = IOMMU_RESV_DIRECT; + length = entry->address_end - entry->address_start; + if (entry->prot & IOMMU_PROT_IR) + prot |= IOMMU_READ; + if (entry->prot & IOMMU_PROT_IW) + prot |= IOMMU_WRITE; ++ if (entry->prot & IOMMU_UNITY_MAP_FLAG_EXCL_RANGE) ++ /* Exclusion range */ ++ type = IOMMU_RESV_RESERVED; + + region = iommu_alloc_resv_region(entry->address_start, +- length, prot, +- IOMMU_RESV_DIRECT); ++ length, prot, type); + if (!region) { + pr_err("Out of memory allocating dm-regions for %s\n", + dev_name(dev)); +diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c +index e062ab9687c7..be3801d43d48 100644 +--- a/drivers/iommu/amd_iommu_init.c ++++ b/drivers/iommu/amd_iommu_init.c +@@ -2001,6 +2001,9 @@ static int __init init_unity_map_range(struct ivmd_header *m) + if (e == NULL) + return -ENOMEM; + ++ if (m->flags & IVMD_FLAG_EXCL_RANGE) ++ init_exclusion_range(m); ++ + switch (m->type) { + default: + kfree(e); +@@ -2047,9 +2050,7 @@ static int __init init_memory_definitions(struct acpi_table_header *table) + + while (p < end) { + m = (struct ivmd_header *)p; +- if (m->flags & IVMD_FLAG_EXCL_RANGE) +- init_exclusion_range(m); +- else if (m->flags & IVMD_FLAG_UNITY_MAP) ++ if (m->flags & (IVMD_FLAG_UNITY_MAP | IVMD_FLAG_EXCL_RANGE)) + init_unity_map_range(m); + + p += m->length; +diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h +index e2b342e65a7b..69f3d4c95b53 100644 +--- a/drivers/iommu/amd_iommu_types.h ++++ b/drivers/iommu/amd_iommu_types.h +@@ -373,6 +373,8 @@ + #define IOMMU_PROT_IR 0x01 + #define IOMMU_PROT_IW 0x02 + ++#define IOMMU_UNITY_MAP_FLAG_EXCL_RANGE (1 << 2) ++ + /* IOMMU capabilities */ + #define IOMMU_CAP_IOTLB 24 + #define IOMMU_CAP_NPCACHE 26 +diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c +index 7fea18b0c15d..7cb4d685a1f1 100644 +--- a/drivers/leds/leds-pca9532.c ++++ b/drivers/leds/leds-pca9532.c +@@ -513,6 +513,7 @@ static int pca9532_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { + int devid; ++ const struct of_device_id *of_id; + struct pca9532_data *data = i2c_get_clientdata(client); + struct pca9532_platform_data *pca9532_pdata = + dev_get_platdata(&client->dev); +@@ -528,8 +529,11 @@ static int pca9532_probe(struct i2c_client *client, + dev_err(&client->dev, "no platform data\n"); + return -EINVAL; + } +- devid = (int)(uintptr_t)of_match_device( +- of_pca9532_leds_match, &client->dev)->data; ++ of_id = of_match_device(of_pca9532_leds_match, ++ &client->dev); ++ if (unlikely(!of_id)) ++ return -EINVAL; ++ devid = (int)(uintptr_t) of_id->data; + } else { + devid = id->driver_data; + } +diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c +index 3dd3ed46d473..136f86a1627d 100644 +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -122,7 +122,8 @@ static ssize_t device_name_store(struct device *dev, + trigger_data->net_dev = NULL; + } + +- strncpy(trigger_data->device_name, buf, size); ++ memcpy(trigger_data->device_name, buf, size); ++ trigger_data->device_name[size] = 0; + if (size > 0 && trigger_data->device_name[size - 1] == '\n') + trigger_data->device_name[size - 1] = 0; + +@@ -301,11 +302,11 @@ static int netdev_trig_notify(struct notifier_block *nb, + container_of(nb, struct led_netdev_data, notifier); + + if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE +- && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER +- && evt != NETDEV_CHANGENAME) ++ && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER) + return NOTIFY_DONE; + +- if (strcmp(dev->name, trigger_data->device_name)) ++ if (!(dev == trigger_data->net_dev || ++ (evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name)))) + return NOTIFY_DONE; + + cancel_delayed_work_sync(&trigger_data->work); +@@ -320,12 +321,9 @@ static int netdev_trig_notify(struct notifier_block *nb, + dev_hold(dev); + trigger_data->net_dev = dev; + break; +- case NETDEV_CHANGENAME: + case NETDEV_UNREGISTER: +- if (trigger_data->net_dev) { +- dev_put(trigger_data->net_dev); +- trigger_data->net_dev = NULL; +- } ++ dev_put(trigger_data->net_dev); ++ trigger_data->net_dev = NULL; + break; + case NETDEV_UP: + case NETDEV_CHANGE: +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 8abea1c3844f..7d7b51383adf 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -3323,14 +3323,20 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk, + *hclk = devm_clk_get(&pdev->dev, "hclk"); + } + +- if (IS_ERR(*pclk)) { ++ if (IS_ERR_OR_NULL(*pclk)) { + err = PTR_ERR(*pclk); ++ if (!err) ++ err = -ENODEV; ++ + dev_err(&pdev->dev, "failed to get macb_clk (%u)\n", err); + return err; + } + +- if (IS_ERR(*hclk)) { ++ if (IS_ERR_OR_NULL(*hclk)) { + err = PTR_ERR(*hclk); ++ if (!err) ++ err = -ENODEV; ++ + dev_err(&pdev->dev, "failed to get hclk (%u)\n", err); + return err; + } +diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c +index 03f64f40b2a3..506f78322d74 100644 +--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c ++++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c +@@ -3161,6 +3161,7 @@ static ssize_t ehea_probe_port(struct device *dev, + + if (ehea_add_adapter_mr(adapter)) { + pr_err("creating MR failed\n"); ++ of_node_put(eth_dn); + return -EIO; + } + +diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c +index bd6e9014bc74..b83b070a9eec 100644 +--- a/drivers/net/ethernet/micrel/ks8851.c ++++ b/drivers/net/ethernet/micrel/ks8851.c +@@ -535,9 +535,8 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) + /* set dma read address */ + ks8851_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI | 0x00); + +- /* start the packet dma process, and set auto-dequeue rx */ +- ks8851_wrreg16(ks, KS_RXQCR, +- ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE); ++ /* start DMA access */ ++ ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); + + if (rxlen > 4) { + unsigned int rxalign; +@@ -568,7 +567,8 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) + } + } + +- ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); ++ /* end DMA access and dequeue packet */ ++ ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_RRXEF); + } + } + +@@ -785,6 +785,15 @@ static void ks8851_tx_work(struct work_struct *work) + static int ks8851_net_open(struct net_device *dev) + { + struct ks8851_net *ks = netdev_priv(dev); ++ int ret; ++ ++ ret = request_threaded_irq(dev->irq, NULL, ks8851_irq, ++ IRQF_TRIGGER_LOW | IRQF_ONESHOT, ++ dev->name, ks); ++ if (ret < 0) { ++ netdev_err(dev, "failed to get irq\n"); ++ return ret; ++ } + + /* lock the card, even if we may not actually be doing anything + * else at the moment */ +@@ -849,6 +858,7 @@ static int ks8851_net_open(struct net_device *dev) + netif_dbg(ks, ifup, ks->netdev, "network device up\n"); + + mutex_unlock(&ks->lock); ++ mii_check_link(&ks->mii); + return 0; + } + +@@ -899,6 +909,8 @@ static int ks8851_net_stop(struct net_device *dev) + dev_kfree_skb(txb); + } + ++ free_irq(dev->irq, ks); ++ + return 0; + } + +@@ -1508,6 +1520,7 @@ static int ks8851_probe(struct spi_device *spi) + + spi_set_drvdata(spi, ks); + ++ netif_carrier_off(ks->netdev); + ndev->if_port = IF_PORT_100BASET; + ndev->netdev_ops = &ks8851_netdev_ops; + ndev->irq = spi->irq; +@@ -1529,14 +1542,6 @@ static int ks8851_probe(struct spi_device *spi) + ks8851_read_selftest(ks); + ks8851_init_mac(ks); + +- ret = request_threaded_irq(spi->irq, NULL, ks8851_irq, +- IRQF_TRIGGER_LOW | IRQF_ONESHOT, +- ndev->name, ks); +- if (ret < 0) { +- dev_err(&spi->dev, "failed to get irq\n"); +- goto err_irq; +- } +- + ret = register_netdev(ndev); + if (ret) { + dev_err(&spi->dev, "failed to register network device\n"); +@@ -1549,14 +1554,10 @@ static int ks8851_probe(struct spi_device *spi) + + return 0; + +- + err_netdev: +- free_irq(ndev->irq, ks); +- +-err_irq: ++err_id: + if (gpio_is_valid(gpio)) + gpio_set_value(gpio, 0); +-err_id: + regulator_disable(ks->vdd_reg); + err_reg: + regulator_disable(ks->vdd_io); +@@ -1574,7 +1575,6 @@ static int ks8851_remove(struct spi_device *spi) + dev_info(&spi->dev, "remove\n"); + + unregister_netdev(priv->netdev); +- free_irq(spi->irq, priv); + if (gpio_is_valid(priv->gpio)) + gpio_set_value(priv->gpio, 0); + regulator_disable(priv->vdd_reg); +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +index 3b0adda7cc9c..a4cd6f2cfb86 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +@@ -1048,6 +1048,8 @@ int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) + + for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) { + skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE); ++ if (!skb) ++ break; + qlcnic_create_loopback_buff(skb->data, adapter->mac_addr); + skb_put(skb, QLCNIC_ILB_PKT_SIZE); + adapter->ahw->diag_cnt = 0; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 62460a5b4ad9..39c105092214 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -3195,14 +3195,16 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) + stmmac_prepare_tx_desc(priv, first, 1, nopaged_len, + csum_insertion, priv->mode, 1, last_segment, + skb->len); +- +- /* The own bit must be the latest setting done when prepare the +- * descriptor and then barrier is needed to make sure that +- * all is coherent before granting the DMA engine. +- */ +- wmb(); ++ } else { ++ stmmac_set_tx_owner(priv, first); + } + ++ /* The own bit must be the latest setting done when prepare the ++ * descriptor and then barrier is needed to make sure that ++ * all is coherent before granting the DMA engine. ++ */ ++ wmb(); ++ + netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len); + + stmmac_enable_dma_transmission(priv, priv->ioaddr); +diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c +index 72b98e27c992..d177dfd1df89 100644 +--- a/drivers/net/ethernet/ti/netcp_ethss.c ++++ b/drivers/net/ethernet/ti/netcp_ethss.c +@@ -3655,12 +3655,16 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, + + ret = netcp_txpipe_init(&gbe_dev->tx_pipe, netcp_device, + gbe_dev->dma_chan_name, gbe_dev->tx_queue_id); +- if (ret) ++ if (ret) { ++ of_node_put(interfaces); + return ret; ++ } + + ret = netcp_txpipe_open(&gbe_dev->tx_pipe); +- if (ret) ++ if (ret) { ++ of_node_put(interfaces); + return ret; ++ } + + /* Create network interfaces */ + INIT_LIST_HEAD(&gbe_dev->gbe_intf_head); +diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +index f24f48f33802..7cfd7ff38e86 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -1574,12 +1574,14 @@ static int axienet_probe(struct platform_device *pdev) + ret = of_address_to_resource(np, 0, &dmares); + if (ret) { + dev_err(&pdev->dev, "unable to get DMA resource\n"); ++ of_node_put(np); + goto free_netdev; + } + lp->dma_regs = devm_ioremap_resource(&pdev->dev, &dmares); + if (IS_ERR(lp->dma_regs)) { + dev_err(&pdev->dev, "could not map DMA regs\n"); + ret = PTR_ERR(lp->dma_regs); ++ of_node_put(np); + goto free_netdev; + } + lp->rx_irq = irq_of_parse_and_map(np, 1); +diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c +index cd1d8faccca5..cd6b95e673a5 100644 +--- a/drivers/net/ieee802154/adf7242.c ++++ b/drivers/net/ieee802154/adf7242.c +@@ -1268,6 +1268,10 @@ static int adf7242_probe(struct spi_device *spi) + INIT_DELAYED_WORK(&lp->work, adf7242_rx_cal_work); + lp->wqueue = alloc_ordered_workqueue(dev_name(&spi->dev), + WQ_MEM_RECLAIM); ++ if (unlikely(!lp->wqueue)) { ++ ret = -ENOMEM; ++ goto err_hw_init; ++ } + + ret = adf7242_hw_init(lp); + if (ret) +diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c +index 624bff4d3636..f1ed1744801c 100644 +--- a/drivers/net/ieee802154/mac802154_hwsim.c ++++ b/drivers/net/ieee802154/mac802154_hwsim.c +@@ -332,7 +332,7 @@ static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info) + goto out_err; + } + +- genlmsg_reply(skb, info); ++ res = genlmsg_reply(skb, info); + break; + } + +diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c +index da8f5ad30c71..260248fbb8fe 100644 +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -349,15 +349,12 @@ static inline bool nvme_state_is_live(enum nvme_ana_state state) + static void nvme_update_ns_ana_state(struct nvme_ana_group_desc *desc, + struct nvme_ns *ns) + { +- enum nvme_ana_state old; +- + mutex_lock(&ns->head->lock); +- old = ns->ana_state; + ns->ana_grpid = le32_to_cpu(desc->grpid); + ns->ana_state = desc->state; + clear_bit(NVME_NS_ANA_PENDING, &ns->flags); + +- if (nvme_state_is_live(ns->ana_state) && !nvme_state_is_live(old)) ++ if (nvme_state_is_live(ns->ana_state)) + nvme_mpath_set_live(ns); + mutex_unlock(&ns->head->lock); + } +diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c +index 7f71ca0d08e7..9c5e801b3f6c 100644 +--- a/drivers/s390/net/qeth_l3_main.c ++++ b/drivers/s390/net/qeth_l3_main.c +@@ -2586,12 +2586,14 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev) + struct qeth_card *card = dev_get_drvdata(&gdev->dev); + int rc; + ++ hash_init(card->ip_htable); ++ + if (gdev->dev.type == &qeth_generic_devtype) { + rc = qeth_l3_create_device_attributes(&gdev->dev); + if (rc) + return rc; + } +- hash_init(card->ip_htable); ++ + hash_init(card->ip_mc_htable); + card->options.layer2 = 0; + card->info.hwtrap = 0; +diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c +index f6c415d6ef48..5eb7aabe2d8b 100644 +--- a/drivers/s390/scsi/zfcp_fc.c ++++ b/drivers/s390/scsi/zfcp_fc.c +@@ -239,10 +239,6 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, + list_for_each_entry(port, &adapter->port_list, list) { + if ((port->d_id & range) == (ntoh24(page->rscn_fid) & range)) + zfcp_fc_test_link(port); +- if (!port->d_id) +- zfcp_erp_port_reopen(port, +- ZFCP_STATUS_COMMON_ERP_FAILED, +- "fcrscn1"); + } + read_unlock_irqrestore(&adapter->port_list_lock, flags); + } +@@ -250,6 +246,7 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, + static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) + { + struct fsf_status_read_buffer *status_buffer = (void *)fsf_req->data; ++ struct zfcp_adapter *adapter = fsf_req->adapter; + struct fc_els_rscn *head; + struct fc_els_rscn_page *page; + u16 i; +@@ -263,6 +260,22 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) + no_entries = be16_to_cpu(head->rscn_plen) / + sizeof(struct fc_els_rscn_page); + ++ if (no_entries > 1) { ++ /* handle failed ports */ ++ unsigned long flags; ++ struct zfcp_port *port; ++ ++ read_lock_irqsave(&adapter->port_list_lock, flags); ++ list_for_each_entry(port, &adapter->port_list, list) { ++ if (port->d_id) ++ continue; ++ zfcp_erp_port_reopen(port, ++ ZFCP_STATUS_COMMON_ERP_FAILED, ++ "fcrscn1"); ++ } ++ read_unlock_irqrestore(&adapter->port_list_lock, flags); ++ } ++ + for (i = 1; i < no_entries; i++) { + /* skip head and start with 1st element */ + page++; +diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h +index 39eb415987fc..074760f21014 100644 +--- a/drivers/scsi/aacraid/aacraid.h ++++ b/drivers/scsi/aacraid/aacraid.h +@@ -2639,9 +2639,14 @@ static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor) + return capacity; + } + ++static inline int aac_pci_offline(struct aac_dev *dev) ++{ ++ return pci_channel_offline(dev->pdev) || dev->handle_pci_error; ++} ++ + static inline int aac_adapter_check_health(struct aac_dev *dev) + { +- if (unlikely(pci_channel_offline(dev->pdev))) ++ if (unlikely(aac_pci_offline(dev))) + return -1; + + return (dev)->a_ops.adapter_check_health(dev); +diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c +index 3236240a4edd..b7588de4484e 100644 +--- a/drivers/scsi/aacraid/commsup.c ++++ b/drivers/scsi/aacraid/commsup.c +@@ -673,7 +673,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, + return -ETIMEDOUT; + } + +- if (unlikely(pci_channel_offline(dev->pdev))) ++ if (unlikely(aac_pci_offline(dev))) + return -EFAULT; + + if ((blink = aac_adapter_check_health(dev)) > 0) { +@@ -773,7 +773,7 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback, + + spin_unlock_irqrestore(&fibptr->event_lock, flags); + +- if (unlikely(pci_channel_offline(dev->pdev))) ++ if (unlikely(aac_pci_offline(dev))) + return -EFAULT; + + fibptr->flags |= FIB_CONTEXT_FLAG_WAIT; +diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c +index b59bba3e6516..8776330175e3 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_base.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_base.c +@@ -3280,12 +3280,18 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid) + + if (smid < ioc->hi_priority_smid) { + struct scsiio_tracker *st; ++ void *request; + + st = _get_st_from_smid(ioc, smid); + if (!st) { + _base_recovery_check(ioc); + return; + } ++ ++ /* Clear MPI request frame */ ++ request = mpt3sas_base_get_msg_frame(ioc, smid); ++ memset(request, 0, ioc->request_sz); ++ + mpt3sas_base_clear_st(ioc, st); + _base_recovery_check(ioc); + return; +diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c +index 622832e55211..73d661a0ecbb 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c +@@ -1474,11 +1474,23 @@ mpt3sas_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid) + { + struct scsi_cmnd *scmd = NULL; + struct scsiio_tracker *st; ++ Mpi25SCSIIORequest_t *mpi_request; + + if (smid > 0 && + smid <= ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT) { + u32 unique_tag = smid - 1; + ++ mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); ++ ++ /* ++ * If SCSI IO request is outstanding at driver level then ++ * DevHandle filed must be non-zero. If DevHandle is zero ++ * then it means that this smid is free at driver level, ++ * so return NULL. ++ */ ++ if (!mpi_request->DevHandle) ++ return scmd; ++ + scmd = scsi_host_find_tag(ioc->shost, unique_tag); + if (scmd) { + st = scsi_cmd_priv(scmd); +diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c +index 575445c761b4..5dd3e4e01b10 100644 +--- a/drivers/scsi/qla4xxx/ql4_os.c ++++ b/drivers/scsi/qla4xxx/ql4_os.c +@@ -3204,6 +3204,8 @@ static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session, + if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) + return -EINVAL; + ep = iscsi_lookup_endpoint(transport_fd); ++ if (!ep) ++ return -EINVAL; + conn = cls_conn->dd_data; + qla_conn = conn->dd_data; + qla_conn->qla_ep = ep->dd_data; +diff --git a/drivers/staging/axis-fifo/Kconfig b/drivers/staging/axis-fifo/Kconfig +index 687537203d9c..d9725888af6f 100644 +--- a/drivers/staging/axis-fifo/Kconfig ++++ b/drivers/staging/axis-fifo/Kconfig +@@ -3,6 +3,7 @@ + # + config XIL_AXIS_FIFO + tristate "Xilinx AXI-Stream FIFO IP core driver" ++ depends on OF + default n + help + This adds support for the Xilinx AXI-Stream +diff --git a/drivers/staging/mt7621-pci/Kconfig b/drivers/staging/mt7621-pci/Kconfig +index d33533872a16..c8fa17cfa807 100644 +--- a/drivers/staging/mt7621-pci/Kconfig ++++ b/drivers/staging/mt7621-pci/Kconfig +@@ -1,6 +1,7 @@ + config PCI_MT7621 + tristate "MediaTek MT7621 PCI Controller" + depends on RALINK ++ depends on PCI + select PCI_DRIVERS_GENERIC + help + This selects a driver for the MediaTek MT7621 PCI Controller. +diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c +index 2130d78e0d9f..dd9b02d316f3 100644 +--- a/drivers/staging/rtl8188eu/core/rtw_xmit.c ++++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c +@@ -178,7 +178,9 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) + + pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf; + +- rtw_alloc_hwxmits(padapter); ++ res = rtw_alloc_hwxmits(padapter); ++ if (res == _FAIL) ++ goto exit; + rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); + + for (i = 0; i < 4; i++) +@@ -1502,7 +1504,7 @@ exit: + return res; + } + +-void rtw_alloc_hwxmits(struct adapter *padapter) ++s32 rtw_alloc_hwxmits(struct adapter *padapter) + { + struct hw_xmit *hwxmits; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; +@@ -1511,6 +1513,8 @@ void rtw_alloc_hwxmits(struct adapter *padapter) + + pxmitpriv->hwxmits = kcalloc(pxmitpriv->hwxmit_entry, + sizeof(struct hw_xmit), GFP_KERNEL); ++ if (!pxmitpriv->hwxmits) ++ return _FAIL; + + hwxmits = pxmitpriv->hwxmits; + +@@ -1518,6 +1522,7 @@ void rtw_alloc_hwxmits(struct adapter *padapter) + hwxmits[1] .sta_queue = &pxmitpriv->vi_pending; + hwxmits[2] .sta_queue = &pxmitpriv->be_pending; + hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; ++ return _SUCCESS; + } + + void rtw_free_hwxmits(struct adapter *padapter) +diff --git a/drivers/staging/rtl8188eu/include/rtw_xmit.h b/drivers/staging/rtl8188eu/include/rtw_xmit.h +index 788f59c74ea1..ba7e15fbde72 100644 +--- a/drivers/staging/rtl8188eu/include/rtw_xmit.h ++++ b/drivers/staging/rtl8188eu/include/rtw_xmit.h +@@ -336,7 +336,7 @@ s32 rtw_txframes_sta_ac_pending(struct adapter *padapter, + void rtw_init_hwxmits(struct hw_xmit *phwxmit, int entry); + s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter); + void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv); +-void rtw_alloc_hwxmits(struct adapter *padapter); ++s32 rtw_alloc_hwxmits(struct adapter *padapter); + void rtw_free_hwxmits(struct adapter *padapter); + s32 rtw_xmit(struct adapter *padapter, struct sk_buff **pkt); + +diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c +index b1dfe9f46619..63bc811681d9 100644 +--- a/drivers/staging/rtl8712/rtl8712_cmd.c ++++ b/drivers/staging/rtl8712/rtl8712_cmd.c +@@ -159,17 +159,9 @@ static u8 write_macreg_hdl(struct _adapter *padapter, u8 *pbuf) + + static u8 read_bbreg_hdl(struct _adapter *padapter, u8 *pbuf) + { +- u32 val; +- void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd); + struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; + +- if (pcmd->rsp && pcmd->rspsz > 0) +- memcpy(pcmd->rsp, (u8 *)&val, pcmd->rspsz); +- pcmd_callback = cmd_callback[pcmd->cmdcode].callback; +- if (!pcmd_callback) +- r8712_free_cmd_obj(pcmd); +- else +- pcmd_callback(padapter, pcmd); ++ r8712_free_cmd_obj(pcmd); + return H2C_SUCCESS; + } + +diff --git a/drivers/staging/rtl8712/rtl8712_cmd.h b/drivers/staging/rtl8712/rtl8712_cmd.h +index 9181bb6b04c3..a101a0a50955 100644 +--- a/drivers/staging/rtl8712/rtl8712_cmd.h ++++ b/drivers/staging/rtl8712/rtl8712_cmd.h +@@ -152,7 +152,7 @@ enum rtl8712_h2c_cmd { + static struct _cmd_callback cmd_callback[] = { + {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/ + {GEN_CMD_CODE(_Write_MACREG), NULL}, +- {GEN_CMD_CODE(_Read_BBREG), &r8712_getbbrfreg_cmdrsp_callback}, ++ {GEN_CMD_CODE(_Read_BBREG), NULL}, + {GEN_CMD_CODE(_Write_BBREG), NULL}, + {GEN_CMD_CODE(_Read_RFREG), &r8712_getbbrfreg_cmdrsp_callback}, + {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/ +diff --git a/drivers/staging/rtl8723bs/core/rtw_xmit.c b/drivers/staging/rtl8723bs/core/rtw_xmit.c +index edb678190b4b..16291de5c0d9 100644 +--- a/drivers/staging/rtl8723bs/core/rtw_xmit.c ++++ b/drivers/staging/rtl8723bs/core/rtw_xmit.c +@@ -260,7 +260,9 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) + } + } + +- rtw_alloc_hwxmits(padapter); ++ res = rtw_alloc_hwxmits(padapter); ++ if (res == _FAIL) ++ goto exit; + rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); + + for (i = 0; i < 4; i++) { +@@ -2144,7 +2146,7 @@ exit: + return res; + } + +-void rtw_alloc_hwxmits(struct adapter *padapter) ++s32 rtw_alloc_hwxmits(struct adapter *padapter) + { + struct hw_xmit *hwxmits; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; +@@ -2155,10 +2157,8 @@ void rtw_alloc_hwxmits(struct adapter *padapter) + + pxmitpriv->hwxmits = rtw_zmalloc(sizeof(struct hw_xmit) * pxmitpriv->hwxmit_entry); + +- if (pxmitpriv->hwxmits == NULL) { +- DBG_871X("alloc hwxmits fail!...\n"); +- return; +- } ++ if (!pxmitpriv->hwxmits) ++ return _FAIL; + + hwxmits = pxmitpriv->hwxmits; + +@@ -2204,7 +2204,7 @@ void rtw_alloc_hwxmits(struct adapter *padapter) + + } + +- ++ return _SUCCESS; + } + + void rtw_free_hwxmits(struct adapter *padapter) +diff --git a/drivers/staging/rtl8723bs/include/rtw_xmit.h b/drivers/staging/rtl8723bs/include/rtw_xmit.h +index a75b668d09a6..021c72361fbb 100644 +--- a/drivers/staging/rtl8723bs/include/rtw_xmit.h ++++ b/drivers/staging/rtl8723bs/include/rtw_xmit.h +@@ -486,7 +486,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter); + void _rtw_free_xmit_priv (struct xmit_priv *pxmitpriv); + + +-void rtw_alloc_hwxmits(struct adapter *padapter); ++s32 rtw_alloc_hwxmits(struct adapter *padapter); + void rtw_free_hwxmits(struct adapter *padapter); + + +diff --git a/drivers/staging/rtlwifi/phydm/rtl_phydm.c b/drivers/staging/rtlwifi/phydm/rtl_phydm.c +index 9930ed954abb..4cc77b2016e1 100644 +--- a/drivers/staging/rtlwifi/phydm/rtl_phydm.c ++++ b/drivers/staging/rtlwifi/phydm/rtl_phydm.c +@@ -180,6 +180,8 @@ static int rtl_phydm_init_priv(struct rtl_priv *rtlpriv, + + rtlpriv->phydm.internal = + kzalloc(sizeof(struct phy_dm_struct), GFP_KERNEL); ++ if (!rtlpriv->phydm.internal) ++ return 0; + + _rtl_phydm_init_com_info(rtlpriv, ic, params); + +diff --git a/drivers/staging/rtlwifi/rtl8822be/fw.c b/drivers/staging/rtlwifi/rtl8822be/fw.c +index a40396614814..c1ed52df05f0 100644 +--- a/drivers/staging/rtlwifi/rtl8822be/fw.c ++++ b/drivers/staging/rtlwifi/rtl8822be/fw.c +@@ -741,6 +741,8 @@ void rtl8822be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) + u1_rsvd_page_loc, 3); + + skb = dev_alloc_skb(totalpacketlen); ++ if (!skb) ++ return; + memcpy((u8 *)skb_put(skb, totalpacketlen), &reserved_page_packet, + totalpacketlen); + +diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c +index db5df3d54818..3bdd56a1021b 100644 +--- a/drivers/tty/serial/ar933x_uart.c ++++ b/drivers/tty/serial/ar933x_uart.c +@@ -49,11 +49,6 @@ struct ar933x_uart_port { + struct clk *clk; + }; + +-static inline bool ar933x_uart_console_enabled(void) +-{ +- return IS_ENABLED(CONFIG_SERIAL_AR933X_CONSOLE); +-} +- + static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up, + int offset) + { +@@ -508,6 +503,7 @@ static const struct uart_ops ar933x_uart_ops = { + .verify_port = ar933x_uart_verify_port, + }; + ++#ifdef CONFIG_SERIAL_AR933X_CONSOLE + static struct ar933x_uart_port * + ar933x_console_ports[CONFIG_SERIAL_AR933X_NR_UARTS]; + +@@ -604,14 +600,7 @@ static struct console ar933x_uart_console = { + .index = -1, + .data = &ar933x_uart_driver, + }; +- +-static void ar933x_uart_add_console_port(struct ar933x_uart_port *up) +-{ +- if (!ar933x_uart_console_enabled()) +- return; +- +- ar933x_console_ports[up->port.line] = up; +-} ++#endif /* CONFIG_SERIAL_AR933X_CONSOLE */ + + static struct uart_driver ar933x_uart_driver = { + .owner = THIS_MODULE, +@@ -700,7 +689,9 @@ static int ar933x_uart_probe(struct platform_device *pdev) + baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP); + up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD); + +- ar933x_uart_add_console_port(up); ++#ifdef CONFIG_SERIAL_AR933X_CONSOLE ++ ar933x_console_ports[up->port.line] = up; ++#endif + + ret = uart_add_one_port(&ar933x_uart_driver, &up->port); + if (ret) +@@ -749,8 +740,9 @@ static int __init ar933x_uart_init(void) + { + int ret; + +- if (ar933x_uart_console_enabled()) +- ar933x_uart_driver.cons = &ar933x_uart_console; ++#ifdef CONFIG_SERIAL_AR933X_CONSOLE ++ ar933x_uart_driver.cons = &ar933x_uart_console; ++#endif + + ret = uart_register_driver(&ar933x_uart_driver); + if (ret) +diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c +index 47b41159a8bc..55b178c1bd65 100644 +--- a/drivers/tty/serial/sc16is7xx.c ++++ b/drivers/tty/serial/sc16is7xx.c +@@ -1481,7 +1481,7 @@ static int __init sc16is7xx_init(void) + ret = i2c_add_driver(&sc16is7xx_i2c_uart_driver); + if (ret < 0) { + pr_err("failed to init sc16is7xx i2c --> %d\n", ret); +- return ret; ++ goto err_i2c; + } + #endif + +@@ -1489,10 +1489,18 @@ static int __init sc16is7xx_init(void) + ret = spi_register_driver(&sc16is7xx_spi_uart_driver); + if (ret < 0) { + pr_err("failed to init sc16is7xx spi --> %d\n", ret); +- return ret; ++ goto err_spi; + } + #endif + return ret; ++ ++err_spi: ++#ifdef CONFIG_SERIAL_SC16IS7XX_I2C ++ i2c_del_driver(&sc16is7xx_i2c_uart_driver); ++#endif ++err_i2c: ++ uart_unregister_driver(&sc16is7xx_uart); ++ return ret; + } + module_init(sc16is7xx_init); + +diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c +index fdc6e4e403e8..8cced3609e24 100644 +--- a/drivers/usb/dwc3/dwc3-pci.c ++++ b/drivers/usb/dwc3/dwc3-pci.c +@@ -29,6 +29,7 @@ + #define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa + #define PCI_DEVICE_ID_INTEL_APL 0x5aaa + #define PCI_DEVICE_ID_INTEL_KBP 0xa2b0 ++#define PCI_DEVICE_ID_INTEL_CMLH 0x02ee + #define PCI_DEVICE_ID_INTEL_GLK 0x31aa + #define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee + #define PCI_DEVICE_ID_INTEL_CNPH 0xa36e +@@ -305,6 +306,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = { + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD), + (kernel_ulong_t) &dwc3_pci_mrfld_properties, }, + ++ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLH), ++ (kernel_ulong_t) &dwc3_pci_intel_properties, }, ++ + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SPTLP), + (kernel_ulong_t) &dwc3_pci_intel_properties, }, + +diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c +index b77f3126580e..c2011cd7df8c 100644 +--- a/drivers/usb/gadget/udc/net2272.c ++++ b/drivers/usb/gadget/udc/net2272.c +@@ -945,6 +945,7 @@ net2272_dequeue(struct usb_ep *_ep, struct usb_request *_req) + break; + } + if (&req->req != _req) { ++ ep->stopped = stopped; + spin_unlock_irqrestore(&ep->dev->lock, flags); + return -EINVAL; + } +diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c +index b02ab2a8d927..ee872cad5270 100644 +--- a/drivers/usb/gadget/udc/net2280.c ++++ b/drivers/usb/gadget/udc/net2280.c +@@ -866,9 +866,6 @@ static void start_queue(struct net2280_ep *ep, u32 dmactl, u32 td_dma) + (void) readl(&ep->dev->pci->pcimstctl); + + writel(BIT(DMA_START), &dma->dmastat); +- +- if (!ep->is_in) +- stop_out_naking(ep); + } + + static void start_dma(struct net2280_ep *ep, struct net2280_request *req) +@@ -907,6 +904,7 @@ static void start_dma(struct net2280_ep *ep, struct net2280_request *req) + writel(BIT(DMA_START), &dma->dmastat); + return; + } ++ stop_out_naking(ep); + } + + tmp = dmactl_default; +@@ -1275,9 +1273,9 @@ static int net2280_dequeue(struct usb_ep *_ep, struct usb_request *_req) + break; + } + if (&req->req != _req) { ++ ep->stopped = stopped; + spin_unlock_irqrestore(&ep->dev->lock, flags); +- dev_err(&ep->dev->pdev->dev, "%s: Request mismatch\n", +- __func__); ++ ep_dbg(ep->dev, "%s: Request mismatch\n", __func__); + return -EINVAL; + } + +diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c +index 5b8a3d9530c4..5cac83aaeac3 100644 +--- a/drivers/usb/host/u132-hcd.c ++++ b/drivers/usb/host/u132-hcd.c +@@ -3202,6 +3202,9 @@ static int __init u132_hcd_init(void) + printk(KERN_INFO "driver %s\n", hcd_name); + workqueue = create_singlethread_workqueue("u132"); + retval = platform_driver_register(&u132_platform_driver); ++ if (retval) ++ destroy_workqueue(workqueue); ++ + return retval; + } + +diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c +index a6efb9a72939..5f7734c729b1 100644 +--- a/drivers/usb/misc/usb251xb.c ++++ b/drivers/usb/misc/usb251xb.c +@@ -601,7 +601,7 @@ static int usb251xb_probe(struct usb251xb *hub) + dev); + int err; + +- if (np) { ++ if (np && of_id) { + err = usb251xb_get_ofdata(hub, + (struct usb251xb_data *)of_id->data); + if (err) { +diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c +index 4055ab4d5c52..3e518c2ae2bf 100644 +--- a/fs/ceph/inode.c ++++ b/fs/ceph/inode.c +@@ -524,6 +524,7 @@ static void ceph_i_callback(struct rcu_head *head) + struct inode *inode = container_of(head, struct inode, i_rcu); + struct ceph_inode_info *ci = ceph_inode(inode); + ++ kfree(ci->i_symlink); + kmem_cache_free(ceph_inode_cachep, ci); + } + +@@ -561,7 +562,6 @@ void ceph_destroy_inode(struct inode *inode) + ceph_put_snap_realm(mdsc, realm); + } + +- kfree(ci->i_symlink); + while ((n = rb_first(&ci->i_fragtree)) != NULL) { + frag = rb_entry(n, struct ceph_inode_frag, node); + rb_erase(n, &ci->i_fragtree); +diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c +index baaed4d05b22..249de20f752a 100644 +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -1989,10 +1989,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, + rem += pipe->bufs[(pipe->curbuf + idx) & (pipe->buffers - 1)].len; + + ret = -EINVAL; +- if (rem < len) { +- pipe_unlock(pipe); +- goto out; +- } ++ if (rem < len) ++ goto out_free; + + rem = len; + while (rem) { +@@ -2010,7 +2008,9 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, + pipe->curbuf = (pipe->curbuf + 1) & (pipe->buffers - 1); + pipe->nrbufs--; + } else { +- pipe_buf_get(pipe, ibuf); ++ if (!pipe_buf_get(pipe, ibuf)) ++ goto out_free; ++ + *obuf = *ibuf; + obuf->flags &= ~PIPE_BUF_FLAG_GIFT; + obuf->len = rem; +@@ -2033,11 +2033,11 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, + ret = fuse_dev_do_write(fud, &cs, len); + + pipe_lock(pipe); ++out_free: + for (idx = 0; idx < nbuf; idx++) + pipe_buf_release(pipe, &bufs[idx]); + pipe_unlock(pipe); + +-out: + kvfree(bufs); + return ret; + } +diff --git a/fs/nfs/client.c b/fs/nfs/client.c +index 96d5f8135eb9..751ca65da8a3 100644 +--- a/fs/nfs/client.c ++++ b/fs/nfs/client.c +@@ -459,7 +459,7 @@ void nfs_init_timeout_values(struct rpc_timeout *to, int proto, + case XPRT_TRANSPORT_RDMA: + if (retrans == NFS_UNSPEC_RETRANS) + to->to_retries = NFS_DEF_TCP_RETRANS; +- if (timeo == NFS_UNSPEC_TIMEO || to->to_retries == 0) ++ if (timeo == NFS_UNSPEC_TIMEO || to->to_initval == 0) + to->to_initval = NFS_DEF_TCP_TIMEO * HZ / 10; + if (to->to_initval > NFS_MAX_TCP_TIMEOUT) + to->to_initval = NFS_MAX_TCP_TIMEOUT; +diff --git a/fs/pipe.c b/fs/pipe.c +index c51750ed4011..2a297bce381f 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -189,9 +189,9 @@ EXPORT_SYMBOL(generic_pipe_buf_steal); + * in the tee() system call, when we duplicate the buffers in one + * pipe into another. + */ +-void generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf) ++bool generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf) + { +- get_page(buf->page); ++ return try_get_page(buf->page); + } + EXPORT_SYMBOL(generic_pipe_buf_get); + +diff --git a/fs/splice.c b/fs/splice.c +index c78e0e3ff6c4..485e409ef841 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -1584,7 +1584,11 @@ retry: + * Get a reference to this pipe buffer, + * so we can copy the contents over. + */ +- pipe_buf_get(ipipe, ibuf); ++ if (!pipe_buf_get(ipipe, ibuf)) { ++ if (ret == 0) ++ ret = -EFAULT; ++ break; ++ } + *obuf = *ibuf; + + /* +@@ -1658,7 +1662,11 @@ static int link_pipe(struct pipe_inode_info *ipipe, + * Get a reference to this pipe buffer, + * so we can copy the contents over. + */ +- pipe_buf_get(ipipe, ibuf); ++ if (!pipe_buf_get(ipipe, ibuf)) { ++ if (ret == 0) ++ ret = -EFAULT; ++ break; ++ } + + obuf = opipe->bufs + nbuf; + *obuf = *ibuf; +diff --git a/include/linux/mm.h b/include/linux/mm.h +index e899460f1bc5..bdec425c8e14 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -915,6 +915,10 @@ static inline bool is_device_public_page(const struct page *page) + } + #endif /* CONFIG_DEV_PAGEMAP_OPS */ + ++/* 127: arbitrary random number, small enough to assemble well */ ++#define page_ref_zero_or_close_to_overflow(page) \ ++ ((unsigned int) page_ref_count(page) + 127u <= 127u) ++ + static inline void get_page(struct page *page) + { + page = compound_head(page); +@@ -922,8 +926,17 @@ static inline void get_page(struct page *page) + * Getting a normal page or the head of a compound page + * requires to already have an elevated page->_refcount. + */ +- VM_BUG_ON_PAGE(page_ref_count(page) <= 0, page); ++ VM_BUG_ON_PAGE(page_ref_zero_or_close_to_overflow(page), page); ++ page_ref_inc(page); ++} ++ ++static inline __must_check bool try_get_page(struct page *page) ++{ ++ page = compound_head(page); ++ if (WARN_ON_ONCE(page_ref_count(page) <= 0)) ++ return false; + page_ref_inc(page); ++ return true; + } + + static inline void put_page(struct page *page) +diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h +index 66ee63cd5968..7897a3cc05b9 100644 +--- a/include/linux/pipe_fs_i.h ++++ b/include/linux/pipe_fs_i.h +@@ -108,18 +108,20 @@ struct pipe_buf_operations { + /* + * Get a reference to the pipe buffer. + */ +- void (*get)(struct pipe_inode_info *, struct pipe_buffer *); ++ bool (*get)(struct pipe_inode_info *, struct pipe_buffer *); + }; + + /** + * pipe_buf_get - get a reference to a pipe_buffer + * @pipe: the pipe that the buffer belongs to + * @buf: the buffer to get a reference to ++ * ++ * Return: %true if the reference was successfully obtained. + */ +-static inline void pipe_buf_get(struct pipe_inode_info *pipe, ++static inline __must_check bool pipe_buf_get(struct pipe_inode_info *pipe, + struct pipe_buffer *buf) + { +- buf->ops->get(pipe, buf); ++ return buf->ops->get(pipe, buf); + } + + /** +@@ -178,7 +180,7 @@ struct pipe_inode_info *alloc_pipe_info(void); + void free_pipe_info(struct pipe_inode_info *); + + /* Generic pipe buffer ops functions */ +-void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *); ++bool generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *); + int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *); + int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *); + int generic_pipe_buf_nosteal(struct pipe_inode_info *, struct pipe_buffer *); +diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h +index 1be35729c2c5..660d78c9af6c 100644 +--- a/include/linux/sched/signal.h ++++ b/include/linux/sched/signal.h +@@ -417,10 +417,20 @@ static inline void set_restore_sigmask(void) + set_thread_flag(TIF_RESTORE_SIGMASK); + WARN_ON(!test_thread_flag(TIF_SIGPENDING)); + } ++ ++static inline void clear_tsk_restore_sigmask(struct task_struct *tsk) ++{ ++ clear_tsk_thread_flag(tsk, TIF_RESTORE_SIGMASK); ++} ++ + static inline void clear_restore_sigmask(void) + { + clear_thread_flag(TIF_RESTORE_SIGMASK); + } ++static inline bool test_tsk_restore_sigmask(struct task_struct *tsk) ++{ ++ return test_tsk_thread_flag(tsk, TIF_RESTORE_SIGMASK); ++} + static inline bool test_restore_sigmask(void) + { + return test_thread_flag(TIF_RESTORE_SIGMASK); +@@ -438,6 +448,10 @@ static inline void set_restore_sigmask(void) + current->restore_sigmask = true; + WARN_ON(!test_thread_flag(TIF_SIGPENDING)); + } ++static inline void clear_tsk_restore_sigmask(struct task_struct *tsk) ++{ ++ tsk->restore_sigmask = false; ++} + static inline void clear_restore_sigmask(void) + { + current->restore_sigmask = false; +@@ -446,6 +460,10 @@ static inline bool test_restore_sigmask(void) + { + return current->restore_sigmask; + } ++static inline bool test_tsk_restore_sigmask(struct task_struct *tsk) ++{ ++ return tsk->restore_sigmask; ++} + static inline bool test_and_clear_restore_sigmask(void) + { + if (!current->restore_sigmask) +diff --git a/include/net/tc_act/tc_gact.h b/include/net/tc_act/tc_gact.h +index ef8dd0db70ce..56935bf027a7 100644 +--- a/include/net/tc_act/tc_gact.h ++++ b/include/net/tc_act/tc_gact.h +@@ -56,7 +56,7 @@ static inline bool is_tcf_gact_goto_chain(const struct tc_action *a) + + static inline u32 tcf_gact_goto_chain_index(const struct tc_action *a) + { +- return a->goto_chain->index; ++ return READ_ONCE(a->tcfa_action) & TC_ACT_EXT_VAL_MASK; + } + + #endif /* __NET_TC_GACT_H */ +diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h +index 7161856bcf9c..c2c10cc9ffa0 100644 +--- a/include/net/xdp_sock.h ++++ b/include/net/xdp_sock.h +@@ -34,7 +34,6 @@ struct xdp_umem { + u32 headroom; + u32 chunk_size_nohr; + struct user_struct *user; +- struct pid *pid; + unsigned long address; + refcount_t users; + struct work_struct work; +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 21fec73d45d4..fc0d667f5792 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + /* + * Access another process' address space via ptrace. +@@ -925,18 +926,26 @@ int ptrace_request(struct task_struct *child, long request, + ret = ptrace_setsiginfo(child, &siginfo); + break; + +- case PTRACE_GETSIGMASK: ++ case PTRACE_GETSIGMASK: { ++ sigset_t *mask; ++ + if (addr != sizeof(sigset_t)) { + ret = -EINVAL; + break; + } + +- if (copy_to_user(datavp, &child->blocked, sizeof(sigset_t))) ++ if (test_tsk_restore_sigmask(child)) ++ mask = &child->saved_sigmask; ++ else ++ mask = &child->blocked; ++ ++ if (copy_to_user(datavp, mask, sizeof(sigset_t))) + ret = -EFAULT; + else + ret = 0; + + break; ++ } + + case PTRACE_SETSIGMASK: { + sigset_t new_set; +@@ -962,6 +971,8 @@ int ptrace_request(struct task_struct *child, long request, + child->blocked = new_set; + spin_unlock_irq(&child->sighand->siglock); + ++ clear_tsk_restore_sigmask(child); ++ + ret = 0; + break; + } +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 5455ee05bc3b..1bd7a758583b 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -6823,12 +6823,16 @@ static void buffer_pipe_buf_release(struct pipe_inode_info *pipe, + buf->private = 0; + } + +-static void buffer_pipe_buf_get(struct pipe_inode_info *pipe, ++static bool buffer_pipe_buf_get(struct pipe_inode_info *pipe, + struct pipe_buffer *buf) + { + struct buffer_ref *ref = (struct buffer_ref *)buf->private; + ++ if (refcount_read(&ref->refcount) > INT_MAX/2) ++ return false; ++ + refcount_inc(&ref->refcount); ++ return true; + } + + /* Pipe buffer operations for a buffer. */ +diff --git a/mm/gup.c b/mm/gup.c +index 0a5374e6e82d..caadd31714a5 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -153,7 +153,10 @@ retry: + } + + if (flags & FOLL_GET) { +- get_page(page); ++ if (unlikely(!try_get_page(page))) { ++ page = ERR_PTR(-ENOMEM); ++ goto out; ++ } + + /* drop the pgmap reference now that we hold the page */ + if (pgmap) { +@@ -296,7 +299,10 @@ retry_locked: + if (pmd_trans_unstable(pmd)) + ret = -EBUSY; + } else { +- get_page(page); ++ if (unlikely(!try_get_page(page))) { ++ spin_unlock(ptl); ++ return ERR_PTR(-ENOMEM); ++ } + spin_unlock(ptl); + lock_page(page); + ret = split_huge_page(page); +@@ -480,7 +486,10 @@ static int get_gate_page(struct mm_struct *mm, unsigned long address, + if (is_device_public_page(*page)) + goto unmap; + } +- get_page(*page); ++ if (unlikely(!try_get_page(*page))) { ++ ret = -ENOMEM; ++ goto unmap; ++ } + out: + ret = 0; + unmap: +@@ -1368,6 +1377,20 @@ static void undo_dev_pagemap(int *nr, int nr_start, struct page **pages) + } + } + ++/* ++ * Return the compund head page with ref appropriately incremented, ++ * or NULL if that failed. ++ */ ++static inline struct page *try_get_compound_head(struct page *page, int refs) ++{ ++ struct page *head = compound_head(page); ++ if (WARN_ON_ONCE(page_ref_count(head) < 0)) ++ return NULL; ++ if (unlikely(!page_cache_add_speculative(head, refs))) ++ return NULL; ++ return head; ++} ++ + #ifdef CONFIG_ARCH_HAS_PTE_SPECIAL + static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, + int write, struct page **pages, int *nr) +@@ -1402,9 +1425,9 @@ static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, + + VM_BUG_ON(!pfn_valid(pte_pfn(pte))); + page = pte_page(pte); +- head = compound_head(page); + +- if (!page_cache_get_speculative(head)) ++ head = try_get_compound_head(page, 1); ++ if (!head) + goto pte_unmap; + + if (unlikely(pte_val(pte) != pte_val(*ptep))) { +@@ -1543,8 +1566,8 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, + refs++; + } while (addr += PAGE_SIZE, addr != end); + +- head = compound_head(pmd_page(orig)); +- if (!page_cache_add_speculative(head, refs)) { ++ head = try_get_compound_head(pmd_page(orig), refs); ++ if (!head) { + *nr -= refs; + return 0; + } +@@ -1581,8 +1604,8 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr, + refs++; + } while (addr += PAGE_SIZE, addr != end); + +- head = compound_head(pud_page(orig)); +- if (!page_cache_add_speculative(head, refs)) { ++ head = try_get_compound_head(pud_page(orig), refs); ++ if (!head) { + *nr -= refs; + return 0; + } +@@ -1618,8 +1641,8 @@ static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, unsigned long addr, + refs++; + } while (addr += PAGE_SIZE, addr != end); + +- head = compound_head(pgd_page(orig)); +- if (!page_cache_add_speculative(head, refs)) { ++ head = try_get_compound_head(pgd_page(orig), refs); ++ if (!head) { + *nr -= refs; + return 0; + } +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 9e5f66cbf711..5fb779cda972 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -4299,6 +4299,19 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, + + pfn_offset = (vaddr & ~huge_page_mask(h)) >> PAGE_SHIFT; + page = pte_page(huge_ptep_get(pte)); ++ ++ /* ++ * Instead of doing 'try_get_page()' below in the same_page ++ * loop, just check the count once here. ++ */ ++ if (unlikely(page_count(page) <= 0)) { ++ if (pages) { ++ spin_unlock(ptl); ++ remainder = 0; ++ err = -ENOMEM; ++ break; ++ } ++ } + same_page: + if (pages) { + pages[i] = mem_map_offset(page, pfn_offset); +diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c +index 3b0a03b92080..212c184c1eee 100644 +--- a/net/bridge/br_netfilter_hooks.c ++++ b/net/bridge/br_netfilter_hooks.c +@@ -515,6 +515,7 @@ static unsigned int br_nf_pre_routing(void *priv, + nf_bridge->ipv4_daddr = ip_hdr(skb)->daddr; + + skb->protocol = htons(ETH_P_IP); ++ skb->transport_header = skb->network_header + ip_hdr(skb)->ihl * 4; + + NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->net, state->sk, skb, + skb->dev, NULL, +diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c +index 5811208863b7..09d5e0c7b3ba 100644 +--- a/net/bridge/br_netfilter_ipv6.c ++++ b/net/bridge/br_netfilter_ipv6.c +@@ -235,6 +235,8 @@ unsigned int br_nf_pre_routing_ipv6(void *priv, + nf_bridge->ipv6_daddr = ipv6_hdr(skb)->daddr; + + skb->protocol = htons(ETH_P_IPV6); ++ skb->transport_header = skb->network_header + sizeof(struct ipv6hdr); ++ + NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, state->net, state->sk, skb, + skb->dev, NULL, + br_nf_pre_routing_finish_ipv6); +diff --git a/net/ipv6/netfilter/ip6t_srh.c b/net/ipv6/netfilter/ip6t_srh.c +index 1059894a6f4c..4cb83fb69844 100644 +--- a/net/ipv6/netfilter/ip6t_srh.c ++++ b/net/ipv6/netfilter/ip6t_srh.c +@@ -210,6 +210,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par) + psidoff = srhoff + sizeof(struct ipv6_sr_hdr) + + ((srh->segments_left + 1) * sizeof(struct in6_addr)); + psid = skb_header_pointer(skb, psidoff, sizeof(_psid), &_psid); ++ if (!psid) ++ return false; + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_PSID, + ipv6_masked_addr_cmp(psid, &srhinfo->psid_msk, + &srhinfo->psid_addr))) +@@ -223,6 +225,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par) + nsidoff = srhoff + sizeof(struct ipv6_sr_hdr) + + ((srh->segments_left - 1) * sizeof(struct in6_addr)); + nsid = skb_header_pointer(skb, nsidoff, sizeof(_nsid), &_nsid); ++ if (!nsid) ++ return false; + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_NSID, + ipv6_masked_addr_cmp(nsid, &srhinfo->nsid_msk, + &srhinfo->nsid_addr))) +@@ -233,6 +237,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par) + if (srhinfo->mt_flags & IP6T_SRH_LSID) { + lsidoff = srhoff + sizeof(struct ipv6_sr_hdr); + lsid = skb_header_pointer(skb, lsidoff, sizeof(_lsid), &_lsid); ++ if (!lsid) ++ return false; + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LSID, + ipv6_masked_addr_cmp(lsid, &srhinfo->lsid_msk, + &srhinfo->lsid_addr))) +diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig +index f61c306de1d0..e0fb56d67d42 100644 +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -1003,6 +1003,7 @@ config NETFILTER_XT_TARGET_TEE + depends on NETFILTER_ADVANCED + depends on IPV6 || IPV6=n + depends on !NF_CONNTRACK || NF_CONNTRACK ++ depends on IP6_NF_IPTABLES || !IP6_NF_IPTABLES + select NF_DUP_IPV4 + select NF_DUP_IPV6 if IP6_NF_IPTABLES + ---help--- +diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c +index 0e5ec126f6ad..b3e75f9cb686 100644 +--- a/net/netfilter/nft_set_rbtree.c ++++ b/net/netfilter/nft_set_rbtree.c +@@ -302,10 +302,6 @@ static void *nft_rbtree_deactivate(const struct net *net, + else if (d > 0) + parent = parent->rb_right; + else { +- if (!nft_set_elem_active(&rbe->ext, genmask)) { +- parent = parent->rb_left; +- continue; +- } + if (nft_rbtree_interval_end(rbe) && + !nft_rbtree_interval_end(this)) { + parent = parent->rb_left; +@@ -314,6 +310,9 @@ static void *nft_rbtree_deactivate(const struct net *net, + nft_rbtree_interval_end(this)) { + parent = parent->rb_right; + continue; ++ } else if (!nft_set_elem_active(&rbe->ext, genmask)) { ++ parent = parent->rb_left; ++ continue; + } + nft_rbtree_flush(net, set, rbe); + return rbe; +diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c +index bfe2dbea480b..a3b037fbfecd 100644 +--- a/net/xdp/xdp_umem.c ++++ b/net/xdp/xdp_umem.c +@@ -152,9 +152,6 @@ static void xdp_umem_unaccount_pages(struct xdp_umem *umem) + + static void xdp_umem_release(struct xdp_umem *umem) + { +- struct task_struct *task; +- struct mm_struct *mm; +- + xdp_umem_clear_dev(umem); + + if (umem->fq) { +@@ -169,21 +166,10 @@ static void xdp_umem_release(struct xdp_umem *umem) + + xdp_umem_unpin_pages(umem); + +- task = get_pid_task(umem->pid, PIDTYPE_PID); +- put_pid(umem->pid); +- if (!task) +- goto out; +- mm = get_task_mm(task); +- put_task_struct(task); +- if (!mm) +- goto out; +- +- mmput(mm); + kfree(umem->pages); + umem->pages = NULL; + + xdp_umem_unaccount_pages(umem); +-out: + kfree(umem); + } + +@@ -312,7 +298,6 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) + if (size_chk < 0) + return -EINVAL; + +- umem->pid = get_task_pid(current, PIDTYPE_PID); + umem->address = (unsigned long)addr; + umem->props.chunk_mask = ~((u64)chunk_size - 1); + umem->props.size = size; +@@ -328,7 +313,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) + + err = xdp_umem_account_pages(umem); + if (err) +- goto out; ++ return err; + + err = xdp_umem_pin_pages(umem); + if (err) +@@ -347,8 +332,6 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) + + out_account: + xdp_umem_unaccount_pages(umem); +-out: +- put_pid(umem->pid); + return err; + } + +diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c +index fe82ff6d744e..b15c8d1744f5 100644 +--- a/scripts/kconfig/lxdialog/inputbox.c ++++ b/scripts/kconfig/lxdialog/inputbox.c +@@ -126,7 +126,8 @@ do_resize: + case KEY_DOWN: + break; + case KEY_BACKSPACE: +- case 127: ++ case 8: /* ^H */ ++ case 127: /* ^? */ + if (pos) { + wattrset(dialog, dlg.inputbox.atr); + if (input_x == 0) { +diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c +index 1ef232ae5ab9..c8ff1c99dd5c 100644 +--- a/scripts/kconfig/nconf.c ++++ b/scripts/kconfig/nconf.c +@@ -1049,7 +1049,7 @@ static int do_match(int key, struct match_state *state, int *ans) + state->match_direction = FIND_NEXT_MATCH_UP; + *ans = get_mext_match(state->pattern, + state->match_direction); +- } else if (key == KEY_BACKSPACE || key == 127) { ++ } else if (key == KEY_BACKSPACE || key == 8 || key == 127) { + state->pattern[strlen(state->pattern)-1] = '\0'; + adj_match_dir(&state->match_direction); + } else +diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c +index 88874acfda36..820fc9256532 100644 +--- a/scripts/kconfig/nconf.gui.c ++++ b/scripts/kconfig/nconf.gui.c +@@ -440,7 +440,8 @@ int dialog_inputbox(WINDOW *main_window, + case KEY_F(F_EXIT): + case KEY_F(F_BACK): + break; +- case 127: ++ case 8: /* ^H */ ++ case 127: /* ^? */ + case KEY_BACKSPACE: + if (cursor_position > 0) { + memmove(&result[cursor_position-1], +diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c +index fa48fabcb330..3cc4893d98cc 100644 +--- a/scripts/selinux/genheaders/genheaders.c ++++ b/scripts/selinux/genheaders/genheaders.c +@@ -9,7 +9,6 @@ + #include + #include + #include +-#include + + struct security_class_mapping { + const char *name; +diff --git a/scripts/selinux/mdp/mdp.c b/scripts/selinux/mdp/mdp.c +index 073fe7537f6c..6d51b74bc679 100644 +--- a/scripts/selinux/mdp/mdp.c ++++ b/scripts/selinux/mdp/mdp.c +@@ -32,7 +32,6 @@ + #include + #include + #include +-#include + + static void usage(char *name) + { +diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h +index bd5fe0d3204a..201f7e588a29 100644 +--- a/security/selinux/include/classmap.h ++++ b/security/selinux/include/classmap.h +@@ -1,5 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + #include ++#include + + #define COMMON_FILE_SOCK_PERMS "ioctl", "read", "write", "create", \ + "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append", "map" +diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c +index b1508ce3e412..076718a7b3ea 100644 +--- a/tools/perf/util/machine.c ++++ b/tools/perf/util/machine.c +@@ -1358,6 +1358,20 @@ static void machine__set_kernel_mmap(struct machine *machine, + machine->vmlinux_map->end = ~0ULL; + } + ++static void machine__update_kernel_mmap(struct machine *machine, ++ u64 start, u64 end) ++{ ++ struct map *map = machine__kernel_map(machine); ++ ++ map__get(map); ++ map_groups__remove(&machine->kmaps, map); ++ ++ machine__set_kernel_mmap(machine, start, end); ++ ++ map_groups__insert(&machine->kmaps, map); ++ map__put(map); ++} ++ + int machine__create_kernel_maps(struct machine *machine) + { + struct dso *kernel = machine__get_kernel(machine); +@@ -1390,17 +1404,11 @@ int machine__create_kernel_maps(struct machine *machine) + goto out_put; + } + +- /* we have a real start address now, so re-order the kmaps */ +- map = machine__kernel_map(machine); +- +- map__get(map); +- map_groups__remove(&machine->kmaps, map); +- +- /* assume it's the last in the kmaps */ +- machine__set_kernel_mmap(machine, addr, ~0ULL); +- +- map_groups__insert(&machine->kmaps, map); +- map__put(map); ++ /* ++ * we have a real start address now, so re-order the kmaps ++ * assume it's the last in the kmaps ++ */ ++ machine__update_kernel_mmap(machine, addr, ~0ULL); + } + + if (machine__create_extra_kernel_maps(machine, kernel)) +@@ -1536,7 +1544,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine, + if (strstr(kernel->long_name, "vmlinux")) + dso__set_short_name(kernel, "[kernel.vmlinux]", false); + +- machine__set_kernel_mmap(machine, event->mmap.start, ++ machine__update_kernel_mmap(machine, event->mmap.start, + event->mmap.start + event->mmap.len); + + /* +diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c +index f376c82afb61..621bb004067e 100644 +--- a/virt/kvm/arm/vgic/vgic-its.c ++++ b/virt/kvm/arm/vgic/vgic-its.c +@@ -760,8 +760,9 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id, + int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K; + u64 indirect_ptr, type = GITS_BASER_TYPE(baser); + int esz = GITS_BASER_ENTRY_SIZE(baser); +- int index; ++ int index, idx; + gfn_t gfn; ++ bool ret; + + switch (type) { + case GITS_BASER_TYPE_DEVICE: +@@ -788,7 +789,8 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id, + + if (eaddr) + *eaddr = addr; +- return kvm_is_visible_gfn(its->dev->kvm, gfn); ++ ++ goto out; + } + + /* calculate and check the index into the 1st level */ +@@ -822,7 +824,12 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id, + + if (eaddr) + *eaddr = indirect_ptr; +- return kvm_is_visible_gfn(its->dev->kvm, gfn); ++ ++out: ++ idx = srcu_read_lock(&its->dev->kvm->srcu); ++ ret = kvm_is_visible_gfn(its->dev->kvm, gfn); ++ srcu_read_unlock(&its->dev->kvm->srcu, idx); ++ return ret; + } + + static int vgic_its_alloc_collection(struct vgic_its *its, +@@ -1935,7 +1942,7 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev, + ((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) | + ite->collection->collection_id; + val = cpu_to_le64(val); +- return kvm_write_guest(kvm, gpa, &val, ite_esz); ++ return kvm_write_guest_lock(kvm, gpa, &val, ite_esz); + } + + /** +@@ -2082,7 +2089,7 @@ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev, + (itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) | + (dev->num_eventid_bits - 1)); + val = cpu_to_le64(val); +- return kvm_write_guest(kvm, ptr, &val, dte_esz); ++ return kvm_write_guest_lock(kvm, ptr, &val, dte_esz); + } + + /** +@@ -2262,7 +2269,7 @@ static int vgic_its_save_cte(struct vgic_its *its, + ((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) | + collection->collection_id); + val = cpu_to_le64(val); +- return kvm_write_guest(its->dev->kvm, gpa, &val, esz); ++ return kvm_write_guest_lock(its->dev->kvm, gpa, &val, esz); + } + + static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz) +@@ -2333,7 +2340,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its) + */ + val = 0; + BUG_ON(cte_esz > sizeof(val)); +- ret = kvm_write_guest(its->dev->kvm, gpa, &val, cte_esz); ++ ret = kvm_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz); + return ret; + } + +diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c +index 9c0dd234ebe8..3f2350a4d4ab 100644 +--- a/virt/kvm/arm/vgic/vgic-v3.c ++++ b/virt/kvm/arm/vgic/vgic-v3.c +@@ -358,7 +358,7 @@ retry: + if (status) { + /* clear consumed data */ + val &= ~(1 << bit_nr); +- ret = kvm_write_guest(kvm, ptr, &val, 1); ++ ret = kvm_write_guest_lock(kvm, ptr, &val, 1); + if (ret) + return ret; + } +@@ -409,7 +409,7 @@ int vgic_v3_save_pending_tables(struct kvm *kvm) + else + val &= ~(1 << bit_nr); + +- ret = kvm_write_guest(kvm, ptr, &val, 1); ++ ret = kvm_write_guest_lock(kvm, ptr, &val, 1); + if (ret) + return ret; + } diff --git a/patch/kernel/sunxi-next/patch-4.19.39-40.patch b/patch/kernel/sunxi-next/patch-4.19.39-40.patch new file mode 100644 index 0000000000..6263b35e04 --- /dev/null +++ b/patch/kernel/sunxi-next/patch-4.19.39-40.patch @@ -0,0 +1,1032 @@ +diff --git a/Makefile b/Makefile +index be1bd297bca9..3822720a8a1c 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 4 + PATCHLEVEL = 19 +-SUBLEVEL = 39 ++SUBLEVEL = 40 + EXTRAVERSION = + NAME = "People's Front" + +diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h +index fd23d5778ea1..f1645578d9d0 100644 +--- a/arch/x86/include/uapi/asm/kvm.h ++++ b/arch/x86/include/uapi/asm/kvm.h +@@ -378,6 +378,7 @@ struct kvm_sync_regs { + #define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0) + #define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1) + #define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2) ++#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3) + + #define KVM_STATE_NESTED_GUEST_MODE 0x00000001 + #define KVM_STATE_NESTED_RUN_PENDING 0x00000002 +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 3380a312d186..215339c7d161 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -14236,7 +14236,7 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, + return ret; + + /* Empty 'VMXON' state is permitted */ +- if (kvm_state->size < sizeof(kvm_state) + sizeof(*vmcs12)) ++ if (kvm_state->size < sizeof(*kvm_state) + sizeof(*vmcs12)) + return 0; + + if (kvm_state->vmx.vmcs_pa == kvm_state->vmx.vmxon_pa || +@@ -14269,7 +14269,7 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, + 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)) ++ if (kvm_state->size < sizeof(*kvm_state) + 2 * sizeof(*vmcs12)) + return -EINVAL; + + if (copy_from_user(shadow_vmcs12, +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 4a61e1609c97..f3337adaf9b3 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -6328,6 +6328,12 @@ int kvm_emulate_instruction_from_buffer(struct kvm_vcpu *vcpu, + } + EXPORT_SYMBOL_GPL(kvm_emulate_instruction_from_buffer); + ++static int complete_fast_pio_out_port_0x7e(struct kvm_vcpu *vcpu) ++{ ++ vcpu->arch.pio.count = 0; ++ return 1; ++} ++ + static int complete_fast_pio_out(struct kvm_vcpu *vcpu) + { + vcpu->arch.pio.count = 0; +@@ -6344,12 +6350,23 @@ static int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, + unsigned long val = kvm_register_read(vcpu, VCPU_REGS_RAX); + int ret = emulator_pio_out_emulated(&vcpu->arch.emulate_ctxt, + size, port, &val, 1); ++ if (ret) ++ return ret; + +- if (!ret) { ++ /* ++ * Workaround userspace that relies on old KVM behavior of %rip being ++ * incremented prior to exiting to userspace to handle "OUT 0x7e". ++ */ ++ if (port == 0x7e && ++ kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_OUT_7E_INC_RIP)) { ++ vcpu->arch.complete_userspace_io = ++ complete_fast_pio_out_port_0x7e; ++ kvm_skip_emulated_instruction(vcpu); ++ } else { + vcpu->arch.pio.linear_rip = kvm_get_linear_rip(vcpu); + vcpu->arch.complete_userspace_io = complete_fast_pio_out; + } +- return ret; ++ return 0; + } + + static int complete_fast_pio_in(struct kvm_vcpu *vcpu) +diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c +index 47c5f272a084..21db1804e85d 100644 +--- a/drivers/net/dsa/bcm_sf2_cfp.c ++++ b/drivers/net/dsa/bcm_sf2_cfp.c +@@ -742,6 +742,9 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port, + fs->m_ext.data[1])) + return -EINVAL; + ++ if (fs->location != RX_CLS_LOC_ANY && fs->location >= CFP_NUM_RULES) ++ return -EINVAL; ++ + if (fs->location != RX_CLS_LOC_ANY && + test_bit(fs->location, priv->cfp.used)) + return -EBUSY; +@@ -836,6 +839,9 @@ static int bcm_sf2_cfp_rule_del(struct bcm_sf2_priv *priv, int port, + u32 next_loc = 0; + int ret; + ++ if (loc >= CFP_NUM_RULES) ++ return -EINVAL; ++ + /* Refuse deleting unused rules, and those that are not unique since + * that could leave IPv6 rules with one of the chained rule in the + * table. +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 581ad0a17d0c..de46331aefc1 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -1584,7 +1584,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons, + netdev_warn(bp->dev, "RX buffer error %x\n", rx_err); + bnxt_sched_reset(bp, rxr); + } +- goto next_rx; ++ goto next_rx_no_len; + } + + len = le32_to_cpu(rxcmp->rx_cmp_len_flags_type) >> RX_CMP_LEN_SHIFT; +@@ -1665,12 +1665,13 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons, + rc = 1; + + next_rx: +- rxr->rx_prod = NEXT_RX(prod); +- rxr->rx_next_cons = NEXT_RX(cons); +- + cpr->rx_packets += 1; + cpr->rx_bytes += len; + ++next_rx_no_len: ++ rxr->rx_prod = NEXT_RX(prod); ++ rxr->rx_next_cons = NEXT_RX(cons); ++ + next_rx_no_prod_no_len: + *raw_cons = tmp_raw_cons; + +@@ -7441,8 +7442,15 @@ static int bnxt_cfg_rx_mode(struct bnxt *bp) + + skip_uc: + rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0); ++ if (rc && vnic->mc_list_count) { ++ netdev_info(bp->dev, "Failed setting MC filters rc: %d, turning on ALL_MCAST mode\n", ++ rc); ++ vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; ++ vnic->mc_list_count = 0; ++ rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0); ++ } + if (rc) +- netdev_err(bp->dev, "HWRM cfa l2 rx mask failure rc: %x\n", ++ netdev_err(bp->dev, "HWRM cfa l2 rx mask failure rc: %d\n", + rc); + + return rc; +@@ -9077,6 +9085,7 @@ init_err_cleanup_tc: + bnxt_clear_int_mode(bp); + + init_err_pci_clean: ++ bnxt_free_hwrm_short_cmd_req(bp); + bnxt_free_hwrm_resources(bp); + bnxt_cleanup_pci(bp); + +diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c +index 73813c7afa49..bb6107f3b947 100644 +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -1513,9 +1513,10 @@ static int marvell_get_sset_count(struct phy_device *phydev) + + static void marvell_get_strings(struct phy_device *phydev, u8 *data) + { ++ int count = marvell_get_sset_count(phydev); + int i; + +- for (i = 0; i < ARRAY_SIZE(marvell_hw_stats); i++) { ++ for (i = 0; i < count; i++) { + strlcpy(data + i * ETH_GSTRING_LEN, + marvell_hw_stats[i].string, ETH_GSTRING_LEN); + } +@@ -1543,9 +1544,10 @@ static u64 marvell_get_stat(struct phy_device *phydev, int i) + static void marvell_get_stats(struct phy_device *phydev, + struct ethtool_stats *stats, u64 *data) + { ++ int count = marvell_get_sset_count(phydev); + int i; + +- for (i = 0; i < ARRAY_SIZE(marvell_hw_stats); i++) ++ for (i = 0; i < count; i++) + data[i] = marvell_get_stat(phydev, i); + } + +diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c +index 90f9372dec25..f3b1cfacfe9d 100644 +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -5622,7 +5622,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, + } + + if (changed & BSS_CHANGED_MCAST_RATE && +- !WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def))) { ++ !ath10k_mac_vif_chan(arvif->vif, &def)) { + band = def.chan->band; + rateidx = vif->bss_conf.mcast_rate[band] - 1; + +diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h +index 6640f84fe536..6d5beac29bc1 100644 +--- a/include/net/sctp/command.h ++++ b/include/net/sctp/command.h +@@ -105,7 +105,6 @@ enum sctp_verb { + SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */ + SCTP_CMD_UPDATE_INITTAG, /* Update peer inittag */ + SCTP_CMD_SEND_MSG, /* Send the whole use message */ +- SCTP_CMD_SEND_NEXT_ASCONF, /* Send the next ASCONF after ACK */ + SCTP_CMD_PURGE_ASCONF_QUEUE, /* Purge all asconf queues.*/ + SCTP_CMD_SET_ASOC, /* Restore association context */ + SCTP_CMD_LAST +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index 9c4e72e9c60a..73894ed12a70 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -519,6 +519,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) + to->pkt_type = from->pkt_type; + to->priority = from->priority; + to->protocol = from->protocol; ++ to->skb_iif = from->skb_iif; + skb_dst_drop(to); + skb_dst_copy(to, from); + to->dev = from->dev; +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index cbe46175bb59..3e2a9bd3459c 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -889,9 +889,7 @@ static void fib6_drop_pcpu_from(struct fib6_info *f6i, + if (pcpu_rt) { + struct fib6_info *from; + +- from = rcu_dereference_protected(pcpu_rt->from, +- lockdep_is_held(&table->tb6_lock)); +- rcu_assign_pointer(pcpu_rt->from, NULL); ++ from = xchg((__force struct fib6_info **)&pcpu_rt->from, NULL); + fib6_info_release(from); + } + } +diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c +index cb54a8a3c273..be5f3d7ceb96 100644 +--- a/net/ipv6/ip6_flowlabel.c ++++ b/net/ipv6/ip6_flowlabel.c +@@ -94,15 +94,21 @@ static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label) + return fl; + } + ++static void fl_free_rcu(struct rcu_head *head) ++{ ++ struct ip6_flowlabel *fl = container_of(head, struct ip6_flowlabel, rcu); ++ ++ if (fl->share == IPV6_FL_S_PROCESS) ++ put_pid(fl->owner.pid); ++ kfree(fl->opt); ++ kfree(fl); ++} ++ + + static void fl_free(struct ip6_flowlabel *fl) + { +- if (fl) { +- if (fl->share == IPV6_FL_S_PROCESS) +- put_pid(fl->owner.pid); +- kfree(fl->opt); +- kfree_rcu(fl, rcu); +- } ++ if (fl) ++ call_rcu(&fl->rcu, fl_free_rcu); + } + + static void fl_release(struct ip6_flowlabel *fl) +@@ -633,9 +639,9 @@ recheck: + if (fl1->share == IPV6_FL_S_EXCL || + fl1->share != fl->share || + ((fl1->share == IPV6_FL_S_PROCESS) && +- (fl1->owner.pid == fl->owner.pid)) || ++ (fl1->owner.pid != fl->owner.pid)) || + ((fl1->share == IPV6_FL_S_USER) && +- uid_eq(fl1->owner.uid, fl->owner.uid))) ++ !uid_eq(fl1->owner.uid, fl->owner.uid))) + goto release; + + err = -ENOMEM; +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 06fa8425d82c..2e519f7b983c 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -382,11 +382,8 @@ static void ip6_dst_destroy(struct dst_entry *dst) + in6_dev_put(idev); + } + +- rcu_read_lock(); +- from = rcu_dereference(rt->from); +- rcu_assign_pointer(rt->from, NULL); ++ from = xchg((__force struct fib6_info **)&rt->from, NULL); + fib6_info_release(from); +- rcu_read_unlock(); + } + + static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, +@@ -1296,9 +1293,7 @@ static void rt6_remove_exception(struct rt6_exception_bucket *bucket, + /* purge completely the exception to allow releasing the held resources: + * some [sk] cache may keep the dst around for unlimited time + */ +- from = rcu_dereference_protected(rt6_ex->rt6i->from, +- lockdep_is_held(&rt6_exception_lock)); +- rcu_assign_pointer(rt6_ex->rt6i->from, NULL); ++ from = xchg((__force struct fib6_info **)&rt6_ex->rt6i->from, NULL); + fib6_info_release(from); + dst_dev_put(&rt6_ex->rt6i->dst); + +@@ -3454,11 +3449,8 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu + + rcu_read_lock(); + from = rcu_dereference(rt->from); +- /* This fib6_info_hold() is safe here because we hold reference to rt +- * and rt already holds reference to fib6_info. +- */ +- fib6_info_hold(from); +- rcu_read_unlock(); ++ if (!from) ++ goto out; + + nrt = ip6_rt_cache_alloc(from, &msg->dest, NULL); + if (!nrt) +@@ -3470,10 +3462,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu + + nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key; + +- /* No need to remove rt from the exception table if rt is +- * a cached route because rt6_insert_exception() will +- * takes care of it +- */ ++ /* rt6_insert_exception() will take care of duplicated exceptions */ + if (rt6_insert_exception(nrt, from)) { + dst_release_immediate(&nrt->dst); + goto out; +@@ -3486,7 +3475,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu + call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); + + out: +- fib6_info_release(from); ++ rcu_read_unlock(); + neigh_release(neigh); + } + +@@ -4991,16 +4980,20 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, + + rcu_read_lock(); + from = rcu_dereference(rt->from); +- +- if (fibmatch) +- err = rt6_fill_node(net, skb, from, NULL, NULL, NULL, iif, +- RTM_NEWROUTE, NETLINK_CB(in_skb).portid, +- nlh->nlmsg_seq, 0); +- else +- err = rt6_fill_node(net, skb, from, dst, &fl6.daddr, +- &fl6.saddr, iif, RTM_NEWROUTE, +- NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, +- 0); ++ if (from) { ++ if (fibmatch) ++ err = rt6_fill_node(net, skb, from, NULL, NULL, NULL, ++ iif, RTM_NEWROUTE, ++ NETLINK_CB(in_skb).portid, ++ nlh->nlmsg_seq, 0); ++ else ++ err = rt6_fill_node(net, skb, from, dst, &fl6.daddr, ++ &fl6.saddr, iif, RTM_NEWROUTE, ++ NETLINK_CB(in_skb).portid, ++ nlh->nlmsg_seq, 0); ++ } else { ++ err = -ENETUNREACH; ++ } + rcu_read_unlock(); + + if (err < 0) { +diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c +index fed6becc5daf..52b5a2797c0c 100644 +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -169,8 +169,8 @@ struct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, u32 tunnel_id) + + rcu_read_lock_bh(); + list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { +- if (tunnel->tunnel_id == tunnel_id) { +- l2tp_tunnel_inc_refcount(tunnel); ++ if (tunnel->tunnel_id == tunnel_id && ++ refcount_inc_not_zero(&tunnel->ref_count)) { + rcu_read_unlock_bh(); + + return tunnel; +@@ -190,8 +190,8 @@ struct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net *net, int nth) + + rcu_read_lock_bh(); + list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { +- if (++count > nth) { +- l2tp_tunnel_inc_refcount(tunnel); ++ if (++count > nth && ++ refcount_inc_not_zero(&tunnel->ref_count)) { + rcu_read_unlock_bh(); + return tunnel; + } +@@ -909,7 +909,7 @@ int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) + { + struct l2tp_tunnel *tunnel; + +- tunnel = l2tp_tunnel(sk); ++ tunnel = rcu_dereference_sk_user_data(sk); + if (tunnel == NULL) + goto pass_up; + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index a0d295478e69..ebbb30064251 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2603,8 +2603,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) + void *ph; + DECLARE_SOCKADDR(struct sockaddr_ll *, saddr, msg->msg_name); + bool need_wait = !(msg->msg_flags & MSG_DONTWAIT); ++ unsigned char *addr = NULL; + int tp_len, size_max; +- unsigned char *addr; + void *data; + int len_sum = 0; + int status = TP_STATUS_AVAILABLE; +@@ -2615,7 +2615,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) + if (likely(saddr == NULL)) { + dev = packet_cached_dev_get(po); + proto = po->num; +- addr = NULL; + } else { + err = -EINVAL; + if (msg->msg_namelen < sizeof(struct sockaddr_ll)) +@@ -2625,10 +2624,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) + sll_addr))) + goto out; + proto = saddr->sll_protocol; +- addr = saddr->sll_halen ? saddr->sll_addr : NULL; + dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex); +- if (addr && dev && saddr->sll_halen < dev->addr_len) +- goto out_put; ++ if (po->sk.sk_socket->type == SOCK_DGRAM) { ++ if (dev && msg->msg_namelen < dev->addr_len + ++ offsetof(struct sockaddr_ll, sll_addr)) ++ goto out_put; ++ addr = saddr->sll_addr; ++ } + } + + err = -ENXIO; +@@ -2800,7 +2802,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) + struct sk_buff *skb; + struct net_device *dev; + __be16 proto; +- unsigned char *addr; ++ unsigned char *addr = NULL; + int err, reserve = 0; + struct sockcm_cookie sockc; + struct virtio_net_hdr vnet_hdr = { 0 }; +@@ -2817,7 +2819,6 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) + if (likely(saddr == NULL)) { + dev = packet_cached_dev_get(po); + proto = po->num; +- addr = NULL; + } else { + err = -EINVAL; + if (msg->msg_namelen < sizeof(struct sockaddr_ll)) +@@ -2825,10 +2826,13 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) + if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr))) + goto out; + proto = saddr->sll_protocol; +- addr = saddr->sll_halen ? saddr->sll_addr : NULL; + dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex); +- if (addr && dev && saddr->sll_halen < dev->addr_len) +- goto out_unlock; ++ if (sock->type == SOCK_DGRAM) { ++ if (dev && msg->msg_namelen < dev->addr_len + ++ offsetof(struct sockaddr_ll, sll_addr)) ++ goto out_unlock; ++ addr = saddr->sll_addr; ++ } + } + + err = -ENXIO; +diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c +index 8f1a8f85b1f9..215f4d98baa0 100644 +--- a/net/rxrpc/call_object.c ++++ b/net/rxrpc/call_object.c +@@ -701,30 +701,30 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet) + + _enter(""); + +- if (list_empty(&rxnet->calls)) +- return; ++ if (!list_empty(&rxnet->calls)) { ++ write_lock(&rxnet->call_lock); + +- write_lock(&rxnet->call_lock); ++ while (!list_empty(&rxnet->calls)) { ++ call = list_entry(rxnet->calls.next, ++ struct rxrpc_call, link); ++ _debug("Zapping call %p", call); + +- while (!list_empty(&rxnet->calls)) { +- call = list_entry(rxnet->calls.next, struct rxrpc_call, link); +- _debug("Zapping call %p", call); ++ rxrpc_see_call(call); ++ list_del_init(&call->link); + +- rxrpc_see_call(call); +- list_del_init(&call->link); ++ pr_err("Call %p still in use (%d,%s,%lx,%lx)!\n", ++ call, atomic_read(&call->usage), ++ rxrpc_call_states[call->state], ++ call->flags, call->events); + +- pr_err("Call %p still in use (%d,%s,%lx,%lx)!\n", +- call, atomic_read(&call->usage), +- rxrpc_call_states[call->state], +- call->flags, call->events); ++ write_unlock(&rxnet->call_lock); ++ cond_resched(); ++ write_lock(&rxnet->call_lock); ++ } + + write_unlock(&rxnet->call_lock); +- cond_resched(); +- write_lock(&rxnet->call_lock); + } + +- write_unlock(&rxnet->call_lock); +- + atomic_dec(&rxnet->nr_calls); + wait_var_event(&rxnet->nr_calls, !atomic_read(&rxnet->nr_calls)); + } +diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c +index 85d393090238..48fe8f01265f 100644 +--- a/net/sctp/sm_sideeffect.c ++++ b/net/sctp/sm_sideeffect.c +@@ -1112,32 +1112,6 @@ static void sctp_cmd_send_msg(struct sctp_association *asoc, + } + + +-/* Sent the next ASCONF packet currently stored in the association. +- * This happens after the ASCONF_ACK was succeffully processed. +- */ +-static void sctp_cmd_send_asconf(struct sctp_association *asoc) +-{ +- struct net *net = sock_net(asoc->base.sk); +- +- /* Send the next asconf chunk from the addip chunk +- * queue. +- */ +- if (!list_empty(&asoc->addip_chunk_list)) { +- struct list_head *entry = asoc->addip_chunk_list.next; +- struct sctp_chunk *asconf = list_entry(entry, +- struct sctp_chunk, list); +- list_del_init(entry); +- +- /* Hold the chunk until an ASCONF_ACK is received. */ +- sctp_chunk_hold(asconf); +- if (sctp_primitive_ASCONF(net, asoc, asconf)) +- sctp_chunk_free(asconf); +- else +- asoc->addip_last_asconf = asconf; +- } +-} +- +- + /* These three macros allow us to pull the debugging code out of the + * main flow of sctp_do_sm() to keep attention focused on the real + * functionality there. +@@ -1783,9 +1757,6 @@ static int sctp_cmd_interpreter(enum sctp_event event_type, + } + sctp_cmd_send_msg(asoc, cmd->obj.msg, gfp); + break; +- case SCTP_CMD_SEND_NEXT_ASCONF: +- sctp_cmd_send_asconf(asoc); +- break; + case SCTP_CMD_PURGE_ASCONF_QUEUE: + sctp_asconf_queue_teardown(asoc); + break; +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index c9ae3404b1bb..713a669d2058 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -3824,6 +3824,29 @@ enum sctp_disposition sctp_sf_do_asconf(struct net *net, + return SCTP_DISPOSITION_CONSUME; + } + ++static enum sctp_disposition sctp_send_next_asconf( ++ struct net *net, ++ const struct sctp_endpoint *ep, ++ struct sctp_association *asoc, ++ const union sctp_subtype type, ++ struct sctp_cmd_seq *commands) ++{ ++ struct sctp_chunk *asconf; ++ struct list_head *entry; ++ ++ if (list_empty(&asoc->addip_chunk_list)) ++ return SCTP_DISPOSITION_CONSUME; ++ ++ entry = asoc->addip_chunk_list.next; ++ asconf = list_entry(entry, struct sctp_chunk, list); ++ ++ list_del_init(entry); ++ sctp_chunk_hold(asconf); ++ asoc->addip_last_asconf = asconf; ++ ++ return sctp_sf_do_prm_asconf(net, ep, asoc, type, asconf, commands); ++} ++ + /* + * ADDIP Section 4.3 General rules for address manipulation + * When building TLV parameters for the ASCONF Chunk that will add or +@@ -3915,14 +3938,10 @@ enum sctp_disposition sctp_sf_do_asconf_ack(struct net *net, + SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); + + if (!sctp_process_asconf_ack((struct sctp_association *)asoc, +- asconf_ack)) { +- /* Successfully processed ASCONF_ACK. We can +- * release the next asconf if we have one. +- */ +- sctp_add_cmd_sf(commands, SCTP_CMD_SEND_NEXT_ASCONF, +- SCTP_NULL()); +- return SCTP_DISPOSITION_CONSUME; +- } ++ asconf_ack)) ++ return sctp_send_next_asconf(net, ep, ++ (struct sctp_association *)asoc, ++ type, commands); + + abort = sctp_make_abort(asoc, asconf_ack, + sizeof(struct sctp_errhdr)); +diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c +index c9588b682db4..f4a19eac975d 100644 +--- a/net/tls/tls_device.c ++++ b/net/tls/tls_device.c +@@ -569,7 +569,7 @@ void handle_device_resync(struct sock *sk, u32 seq, u64 rcd_sn) + static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb) + { + struct strp_msg *rxm = strp_msg(skb); +- int err = 0, offset = rxm->offset, copy, nsg; ++ int err = 0, offset = rxm->offset, copy, nsg, data_len, pos; + struct sk_buff *skb_iter, *unused; + struct scatterlist sg[1]; + char *orig_buf, *buf; +@@ -600,25 +600,42 @@ static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb) + else + err = 0; + +- copy = min_t(int, skb_pagelen(skb) - offset, +- rxm->full_len - TLS_CIPHER_AES_GCM_128_TAG_SIZE); ++ data_len = rxm->full_len - TLS_CIPHER_AES_GCM_128_TAG_SIZE; + +- if (skb->decrypted) +- skb_store_bits(skb, offset, buf, copy); ++ if (skb_pagelen(skb) > offset) { ++ copy = min_t(int, skb_pagelen(skb) - offset, data_len); + +- offset += copy; +- buf += copy; ++ if (skb->decrypted) ++ skb_store_bits(skb, offset, buf, copy); + ++ offset += copy; ++ buf += copy; ++ } ++ ++ pos = skb_pagelen(skb); + skb_walk_frags(skb, skb_iter) { +- copy = min_t(int, skb_iter->len, +- rxm->full_len - offset + rxm->offset - +- TLS_CIPHER_AES_GCM_128_TAG_SIZE); ++ int frag_pos; ++ ++ /* Practically all frags must belong to msg if reencrypt ++ * is needed with current strparser and coalescing logic, ++ * but strparser may "get optimized", so let's be safe. ++ */ ++ if (pos + skb_iter->len <= offset) ++ goto done_with_frag; ++ if (pos >= data_len + rxm->offset) ++ break; ++ ++ frag_pos = offset - pos; ++ copy = min_t(int, skb_iter->len - frag_pos, ++ data_len + rxm->offset - offset); + + if (skb_iter->decrypted) +- skb_store_bits(skb_iter, offset, buf, copy); ++ skb_store_bits(skb_iter, frag_pos, buf, copy); + + offset += copy; + buf += copy; ++done_with_frag: ++ pos += skb_iter->len; + } + + free_buf: +diff --git a/net/tls/tls_device_fallback.c b/net/tls/tls_device_fallback.c +index ef8934fd8698..426dd97725e4 100644 +--- a/net/tls/tls_device_fallback.c ++++ b/net/tls/tls_device_fallback.c +@@ -200,13 +200,14 @@ static void complete_skb(struct sk_buff *nskb, struct sk_buff *skb, int headln) + + skb_put(nskb, skb->len); + memcpy(nskb->data, skb->data, headln); +- update_chksum(nskb, headln); + + nskb->destructor = skb->destructor; + nskb->sk = sk; + skb->destructor = NULL; + skb->sk = NULL; + ++ update_chksum(nskb, headln); ++ + delta = nskb->truesize - skb->truesize; + if (likely(delta < 0)) + WARN_ON_ONCE(refcount_sub_and_test(-delta, &sk->sk_wmem_alloc)); +diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c +index c1376bfdc90b..aa28510d23ad 100644 +--- a/sound/usb/line6/driver.c ++++ b/sound/usb/line6/driver.c +@@ -351,12 +351,16 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, + { + struct usb_device *usbdev = line6->usbdev; + int ret; +- unsigned char len; ++ unsigned char *len; + unsigned count; + + if (address > 0xffff || datalen > 0xff) + return -EINVAL; + ++ len = kmalloc(sizeof(*len), GFP_KERNEL); ++ if (!len) ++ return -ENOMEM; ++ + /* query the serial number: */ + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, +@@ -365,7 +369,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, + + if (ret < 0) { + dev_err(line6->ifcdev, "read request failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + + /* Wait for data length. We'll get 0xff until length arrives. */ +@@ -375,28 +379,29 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | + USB_DIR_IN, +- 0x0012, 0x0000, &len, 1, ++ 0x0012, 0x0000, len, 1, + LINE6_TIMEOUT * HZ); + if (ret < 0) { + dev_err(line6->ifcdev, + "receive length failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + +- if (len != 0xff) ++ if (*len != 0xff) + break; + } + +- if (len == 0xff) { ++ ret = -EIO; ++ if (*len == 0xff) { + dev_err(line6->ifcdev, "read failed after %d retries\n", + count); +- return -EIO; +- } else if (len != datalen) { ++ goto exit; ++ } else if (*len != datalen) { + /* should be equal or something went wrong */ + dev_err(line6->ifcdev, + "length mismatch (expected %d, got %d)\n", +- (int)datalen, (int)len); +- return -EIO; ++ (int)datalen, (int)*len); ++ goto exit; + } + + /* receive the result: */ +@@ -405,12 +410,12 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, + 0x0013, 0x0000, data, datalen, + LINE6_TIMEOUT * HZ); + +- if (ret < 0) { ++ if (ret < 0) + dev_err(line6->ifcdev, "read failed (error %d)\n", ret); +- return ret; +- } + +- return 0; ++exit: ++ kfree(len); ++ return ret; + } + EXPORT_SYMBOL_GPL(line6_read_data); + +@@ -422,12 +427,16 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, + { + struct usb_device *usbdev = line6->usbdev; + int ret; +- unsigned char status; ++ unsigned char *status; + int count; + + if (address > 0xffff || datalen > 0xffff) + return -EINVAL; + ++ status = kmalloc(sizeof(*status), GFP_KERNEL); ++ if (!status) ++ return -ENOMEM; ++ + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + 0x0022, address, data, datalen, +@@ -436,7 +445,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, + if (ret < 0) { + dev_err(line6->ifcdev, + "write request failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + + for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) { +@@ -447,28 +456,29 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | + USB_DIR_IN, + 0x0012, 0x0000, +- &status, 1, LINE6_TIMEOUT * HZ); ++ status, 1, LINE6_TIMEOUT * HZ); + + if (ret < 0) { + dev_err(line6->ifcdev, + "receiving status failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + +- if (status != 0xff) ++ if (*status != 0xff) + break; + } + +- if (status == 0xff) { ++ if (*status == 0xff) { + dev_err(line6->ifcdev, "write failed after %d retries\n", + count); +- return -EIO; +- } else if (status != 0) { ++ ret = -EIO; ++ } else if (*status != 0) { + dev_err(line6->ifcdev, "write failed (error %d)\n", ret); +- return -EIO; ++ ret = -EIO; + } +- +- return 0; ++exit: ++ kfree(status); ++ return ret; + } + EXPORT_SYMBOL_GPL(line6_write_data); + +diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c +index 36ed9c85c0eb..5f3c87264e66 100644 +--- a/sound/usb/line6/podhd.c ++++ b/sound/usb/line6/podhd.c +@@ -225,28 +225,32 @@ static void podhd_startup_start_workqueue(struct timer_list *t) + static int podhd_dev_start(struct usb_line6_podhd *pod) + { + int ret; +- u8 init_bytes[8]; ++ u8 *init_bytes; + int i; + struct usb_device *usbdev = pod->line6.usbdev; + ++ init_bytes = kmalloc(8, GFP_KERNEL); ++ if (!init_bytes) ++ return -ENOMEM; ++ + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), + 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + 0x11, 0, + NULL, 0, LINE6_TIMEOUT * HZ); + if (ret < 0) { + dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + + /* NOTE: looks like some kind of ping message */ + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x11, 0x0, +- &init_bytes, 3, LINE6_TIMEOUT * HZ); ++ init_bytes, 3, LINE6_TIMEOUT * HZ); + if (ret < 0) { + dev_err(pod->line6.ifcdev, + "receive length failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + + pod->firmware_version = +@@ -255,7 +259,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) + for (i = 0; i <= 16; i++) { + ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8); + if (ret < 0) +- return ret; ++ goto exit; + } + + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), +@@ -263,10 +267,9 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) + USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT, + 1, 0, + NULL, 0, LINE6_TIMEOUT * HZ); +- if (ret < 0) +- return ret; +- +- return 0; ++exit: ++ kfree(init_bytes); ++ return ret; + } + + static void podhd_startup_workqueue(struct work_struct *work) +diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c +index f47ba94e6f4a..19bee725de00 100644 +--- a/sound/usb/line6/toneport.c ++++ b/sound/usb/line6/toneport.c +@@ -365,16 +365,21 @@ static bool toneport_has_source_select(struct usb_line6_toneport *toneport) + /* + Setup Toneport device. + */ +-static void toneport_setup(struct usb_line6_toneport *toneport) ++static int toneport_setup(struct usb_line6_toneport *toneport) + { +- u32 ticks; ++ u32 *ticks; + struct usb_line6 *line6 = &toneport->line6; + struct usb_device *usbdev = line6->usbdev; + ++ ticks = kmalloc(sizeof(*ticks), GFP_KERNEL); ++ if (!ticks) ++ return -ENOMEM; ++ + /* sync time on device with host: */ + /* note: 32-bit timestamps overflow in year 2106 */ +- ticks = (u32)ktime_get_real_seconds(); +- line6_write_data(line6, 0x80c6, &ticks, 4); ++ *ticks = (u32)ktime_get_real_seconds(); ++ line6_write_data(line6, 0x80c6, ticks, 4); ++ kfree(ticks); + + /* enable device: */ + toneport_send_cmd(usbdev, 0x0301, 0x0000); +@@ -389,6 +394,7 @@ static void toneport_setup(struct usb_line6_toneport *toneport) + toneport_update_led(toneport); + + mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ); ++ return 0; + } + + /* +@@ -451,7 +457,9 @@ static int toneport_init(struct usb_line6 *line6, + return err; + } + +- toneport_setup(toneport); ++ err = toneport_setup(toneport); ++ if (err) ++ return err; + + /* register audio system: */ + return snd_card_register(line6->card); +@@ -463,7 +471,11 @@ static int toneport_init(struct usb_line6 *line6, + */ + static int toneport_reset_resume(struct usb_interface *interface) + { +- toneport_setup(usb_get_intfdata(interface)); ++ int err; ++ ++ err = toneport_setup(usb_get_intfdata(interface)); ++ if (err) ++ return err; + return line6_resume(interface); + } + #endif +diff --git a/tools/testing/selftests/net/fib_rule_tests.sh b/tools/testing/selftests/net/fib_rule_tests.sh +index d4cfb6a7a086..d84193bdc307 100755 +--- a/tools/testing/selftests/net/fib_rule_tests.sh ++++ b/tools/testing/selftests/net/fib_rule_tests.sh +@@ -27,6 +27,7 @@ log_test() + nsuccess=$((nsuccess+1)) + printf "\n TEST: %-50s [ OK ]\n" "${msg}" + else ++ ret=1 + nfail=$((nfail+1)) + printf "\n TEST: %-50s [FAIL]\n" "${msg}" + if [ "${PAUSE_ON_FAIL}" = "yes" ]; then +@@ -245,4 +246,9 @@ setup + run_fibrule_tests + cleanup + ++if [ "$TESTS" != "none" ]; then ++ printf "\nTests passed: %3d\n" ${nsuccess} ++ printf "Tests failed: %3d\n" ${nfail} ++fi ++ + exit $ret diff --git a/patch/kernel/sunxi-next/patch-4.19.40-41.patch b/patch/kernel/sunxi-next/patch-4.19.40-41.patch new file mode 100644 index 0000000000..6dabf37172 --- /dev/null +++ b/patch/kernel/sunxi-next/patch-4.19.40-41.patch @@ -0,0 +1,3563 @@ +diff --git a/Documentation/driver-api/usb/power-management.rst b/Documentation/driver-api/usb/power-management.rst +index 79beb807996b..4a74cf6f2797 100644 +--- a/Documentation/driver-api/usb/power-management.rst ++++ b/Documentation/driver-api/usb/power-management.rst +@@ -370,11 +370,15 @@ autosuspend the interface's device. When the usage counter is = 0 + then the interface is considered to be idle, and the kernel may + autosuspend the device. + +-Drivers need not be concerned about balancing changes to the usage +-counter; the USB core will undo any remaining "get"s when a driver +-is unbound from its interface. As a corollary, drivers must not call +-any of the ``usb_autopm_*`` functions after their ``disconnect`` +-routine has returned. ++Drivers must be careful to balance their overall changes to the usage ++counter. Unbalanced "get"s will remain in effect when a driver is ++unbound from its interface, preventing the device from going into ++runtime suspend should the interface be bound to a driver again. On ++the other hand, drivers are allowed to achieve this balance by calling ++the ``usb_autopm_*`` functions even after their ``disconnect`` routine ++has returned -- say from within a work-queue routine -- provided they ++retain an active reference to the interface (via ``usb_get_intf`` and ++``usb_put_intf``). + + Drivers using the async routines are responsible for their own + synchronization and mutual exclusion. +diff --git a/Makefile b/Makefile +index 3822720a8a1c..ba3b8504b689 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 4 + PATCHLEVEL = 19 +-SUBLEVEL = 40 ++SUBLEVEL = 41 + EXTRAVERSION = + NAME = "People's Front" + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index e6a36a792bae..c706adf4aed2 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -1261,27 +1261,27 @@ + gpu_opp_table: gpu-opp-table { + compatible = "operating-points-v2"; + +- opp@100000000 { ++ opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <950000>; + }; +- opp@200000000 { ++ opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + opp-microvolt = <950000>; + }; +- opp@300000000 { ++ opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <1000000>; + }; +- opp@400000000 { ++ opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <1100000>; + }; +- opp@500000000 { ++ opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <1200000>; + }; +- opp@600000000 { ++ opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <1250000>; + }; +diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c +index 32fae4dbd63b..0921e2c10edf 100644 +--- a/arch/arm/mach-at91/pm.c ++++ b/arch/arm/mach-at91/pm.c +@@ -594,13 +594,13 @@ static int __init at91_pm_backup_init(void) + + np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam"); + if (!np) +- goto securam_fail; ++ goto securam_fail_no_ref_dev; + + pdev = of_find_device_by_node(np); + of_node_put(np); + if (!pdev) { + pr_warn("%s: failed to find securam device!\n", __func__); +- goto securam_fail; ++ goto securam_fail_no_ref_dev; + } + + sram_pool = gen_pool_get(&pdev->dev, NULL); +@@ -623,6 +623,8 @@ static int __init at91_pm_backup_init(void) + return 0; + + securam_fail: ++ put_device(&pdev->dev); ++securam_fail_no_ref_dev: + iounmap(pm_data.sfrbu); + pm_data.sfrbu = NULL; + return ret; +diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c +index 53c316f7301e..fe4932fda01d 100644 +--- a/arch/arm/mach-iop13xx/setup.c ++++ b/arch/arm/mach-iop13xx/setup.c +@@ -300,7 +300,7 @@ static struct resource iop13xx_adma_2_resources[] = { + } + }; + +-static u64 iop13xx_adma_dmamask = DMA_BIT_MASK(64); ++static u64 iop13xx_adma_dmamask = DMA_BIT_MASK(32); + static struct iop_adma_platform_data iop13xx_adma_0_data = { + .hw_id = 0, + .pool_size = PAGE_SIZE, +@@ -324,7 +324,7 @@ static struct platform_device iop13xx_adma_0_channel = { + .resource = iop13xx_adma_0_resources, + .dev = { + .dma_mask = &iop13xx_adma_dmamask, +- .coherent_dma_mask = DMA_BIT_MASK(64), ++ .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = (void *) &iop13xx_adma_0_data, + }, + }; +@@ -336,7 +336,7 @@ static struct platform_device iop13xx_adma_1_channel = { + .resource = iop13xx_adma_1_resources, + .dev = { + .dma_mask = &iop13xx_adma_dmamask, +- .coherent_dma_mask = DMA_BIT_MASK(64), ++ .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = (void *) &iop13xx_adma_1_data, + }, + }; +@@ -348,7 +348,7 @@ static struct platform_device iop13xx_adma_2_channel = { + .resource = iop13xx_adma_2_resources, + .dev = { + .dma_mask = &iop13xx_adma_dmamask, +- .coherent_dma_mask = DMA_BIT_MASK(64), ++ .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = (void *) &iop13xx_adma_2_data, + }, + }; +diff --git a/arch/arm/mach-iop13xx/tpmi.c b/arch/arm/mach-iop13xx/tpmi.c +index db511ec2b1df..116feb6b261e 100644 +--- a/arch/arm/mach-iop13xx/tpmi.c ++++ b/arch/arm/mach-iop13xx/tpmi.c +@@ -152,7 +152,7 @@ static struct resource iop13xx_tpmi_3_resources[] = { + } + }; + +-u64 iop13xx_tpmi_mask = DMA_BIT_MASK(64); ++u64 iop13xx_tpmi_mask = DMA_BIT_MASK(32); + static struct platform_device iop13xx_tpmi_0_device = { + .name = "iop-tpmi", + .id = 0, +@@ -160,7 +160,7 @@ static struct platform_device iop13xx_tpmi_0_device = { + .resource = iop13xx_tpmi_0_resources, + .dev = { + .dma_mask = &iop13xx_tpmi_mask, +- .coherent_dma_mask = DMA_BIT_MASK(64), ++ .coherent_dma_mask = DMA_BIT_MASK(32), + }, + }; + +@@ -171,7 +171,7 @@ static struct platform_device iop13xx_tpmi_1_device = { + .resource = iop13xx_tpmi_1_resources, + .dev = { + .dma_mask = &iop13xx_tpmi_mask, +- .coherent_dma_mask = DMA_BIT_MASK(64), ++ .coherent_dma_mask = DMA_BIT_MASK(32), + }, + }; + +@@ -182,7 +182,7 @@ static struct platform_device iop13xx_tpmi_2_device = { + .resource = iop13xx_tpmi_2_resources, + .dev = { + .dma_mask = &iop13xx_tpmi_mask, +- .coherent_dma_mask = DMA_BIT_MASK(64), ++ .coherent_dma_mask = DMA_BIT_MASK(32), + }, + }; + +@@ -193,7 +193,7 @@ static struct platform_device iop13xx_tpmi_3_device = { + .resource = iop13xx_tpmi_3_resources, + .dev = { + .dma_mask = &iop13xx_tpmi_mask, +- .coherent_dma_mask = DMA_BIT_MASK(64), ++ .coherent_dma_mask = DMA_BIT_MASK(32), + }, + }; + +diff --git a/arch/arm/plat-iop/adma.c b/arch/arm/plat-iop/adma.c +index a4d1f8de3b5b..d9612221e484 100644 +--- a/arch/arm/plat-iop/adma.c ++++ b/arch/arm/plat-iop/adma.c +@@ -143,7 +143,7 @@ struct platform_device iop3xx_dma_0_channel = { + .resource = iop3xx_dma_0_resources, + .dev = { + .dma_mask = &iop3xx_adma_dmamask, +- .coherent_dma_mask = DMA_BIT_MASK(64), ++ .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = (void *) &iop3xx_dma_0_data, + }, + }; +@@ -155,7 +155,7 @@ struct platform_device iop3xx_dma_1_channel = { + .resource = iop3xx_dma_1_resources, + .dev = { + .dma_mask = &iop3xx_adma_dmamask, +- .coherent_dma_mask = DMA_BIT_MASK(64), ++ .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = (void *) &iop3xx_dma_1_data, + }, + }; +@@ -167,7 +167,7 @@ struct platform_device iop3xx_aau_channel = { + .resource = iop3xx_aau_resources, + .dev = { + .dma_mask = &iop3xx_adma_dmamask, +- .coherent_dma_mask = DMA_BIT_MASK(64), ++ .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = (void *) &iop3xx_aau_data, + }, + }; +diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c +index a2399fd66e97..1e970873439c 100644 +--- a/arch/arm/plat-orion/common.c ++++ b/arch/arm/plat-orion/common.c +@@ -622,7 +622,7 @@ static struct platform_device orion_xor0_shared = { + .resource = orion_xor0_shared_resources, + .dev = { + .dma_mask = &orion_xor_dmamask, +- .coherent_dma_mask = DMA_BIT_MASK(64), ++ .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &orion_xor0_pdata, + }, + }; +@@ -683,7 +683,7 @@ static struct platform_device orion_xor1_shared = { + .resource = orion_xor1_shared_resources, + .dev = { + .dma_mask = &orion_xor_dmamask, +- .coherent_dma_mask = DMA_BIT_MASK(64), ++ .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &orion_xor1_pdata, + }, + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +index 246c317f6a68..91061d9cf78b 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +@@ -94,8 +94,8 @@ + snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 50000>; +- tx_delay = <0x25>; +- rx_delay = <0x11>; ++ tx_delay = <0x24>; ++ rx_delay = <0x18>; + status = "okay"; + }; + +diff --git a/arch/arm64/kernel/sdei.c b/arch/arm64/kernel/sdei.c +index 5ba4465e44f0..ea94cf8f9dc6 100644 +--- a/arch/arm64/kernel/sdei.c ++++ b/arch/arm64/kernel/sdei.c +@@ -94,6 +94,9 @@ static bool on_sdei_normal_stack(unsigned long sp, struct stack_info *info) + unsigned long low = (unsigned long)raw_cpu_read(sdei_stack_normal_ptr); + unsigned long high = low + SDEI_STACK_SIZE; + ++ if (!low) ++ return false; ++ + if (sp < low || sp >= high) + return false; + +@@ -111,6 +114,9 @@ static bool on_sdei_critical_stack(unsigned long sp, struct stack_info *info) + unsigned long low = (unsigned long)raw_cpu_read(sdei_stack_critical_ptr); + unsigned long high = low + SDEI_STACK_SIZE; + ++ if (!low) ++ return false; ++ + if (sp < low || sp >= high) + return false; + +diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c +index 683b5b3805bd..cd381e2291df 100644 +--- a/arch/powerpc/kernel/kvm.c ++++ b/arch/powerpc/kernel/kvm.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -712,6 +713,12 @@ static void kvm_use_magic_page(void) + + static __init void kvm_free_tmp(void) + { ++ /* ++ * Inform kmemleak about the hole in the .bss section since the ++ * corresponding pages will be unmapped with DEBUG_PAGEALLOC=y. ++ */ ++ kmemleak_free_part(&kvm_tmp[kvm_tmp_index], ++ ARRAY_SIZE(kvm_tmp) - kvm_tmp_index); + free_reserved_area(&kvm_tmp[kvm_tmp_index], + &kvm_tmp[ARRAY_SIZE(kvm_tmp)], -1, NULL); + } +diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c +index 4f213ba33491..53e9b58e83c2 100644 +--- a/arch/powerpc/mm/slice.c ++++ b/arch/powerpc/mm/slice.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -376,6 +377,7 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm, + int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); + unsigned long addr, found, prev; + struct vm_unmapped_area_info info; ++ unsigned long min_addr = max(PAGE_SIZE, mmap_min_addr); + + info.flags = VM_UNMAPPED_AREA_TOPDOWN; + info.length = len; +@@ -392,7 +394,7 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm, + if (high_limit > DEFAULT_MAP_WINDOW) + addr += mm->context.slb_addr_limit - DEFAULT_MAP_WINDOW; + +- while (addr > PAGE_SIZE) { ++ while (addr > min_addr) { + info.high_limit = addr; + if (!slice_scan_available(addr - 1, available, 0, &addr)) + continue; +@@ -404,8 +406,8 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm, + * Check if we need to reduce the range, or if we can + * extend it to cover the previous available slice. + */ +- if (addr < PAGE_SIZE) +- addr = PAGE_SIZE; ++ if (addr < min_addr) ++ addr = min_addr; + else if (slice_scan_available(addr - 1, available, 0, &prev)) { + addr = prev; + goto prev_slice; +@@ -527,7 +529,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, + addr = _ALIGN_UP(addr, page_size); + slice_dbg(" aligned addr=%lx\n", addr); + /* Ignore hint if it's too large or overlaps a VMA */ +- if (addr > high_limit - len || ++ if (addr > high_limit - len || addr < mmap_min_addr || + !slice_area_is_free(mm, addr, len)) + addr = 0; + } +diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h +index 8c3e3e3c8be1..f0ea3156192d 100644 +--- a/arch/riscv/include/asm/uaccess.h ++++ b/arch/riscv/include/asm/uaccess.h +@@ -307,7 +307,7 @@ do { \ + " .balign 4\n" \ + "4:\n" \ + " li %0, %6\n" \ +- " jump 2b, %1\n" \ ++ " jump 3b, %1\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .balign " RISCV_SZPTR "\n" \ +diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c +index 26789ad28193..cb99df514a1c 100644 +--- a/arch/sh/boards/of-generic.c ++++ b/arch/sh/boards/of-generic.c +@@ -175,10 +175,10 @@ static struct sh_machine_vector __initmv sh_of_generic_mv = { + + struct sh_clk_ops; + +-void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx) ++void __init __weak arch_init_clk_ops(struct sh_clk_ops **ops, int idx) + { + } + +-void __init plat_irq_setup(void) ++void __init __weak plat_irq_setup(void) + { + } +diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c +index 263af6312329..27ade3cb6482 100644 +--- a/arch/x86/events/amd/core.c ++++ b/arch/x86/events/amd/core.c +@@ -116,6 +116,110 @@ static __initconst const u64 amd_hw_cache_event_ids + }, + }; + ++static __initconst const u64 amd_hw_cache_event_ids_f17h ++ [PERF_COUNT_HW_CACHE_MAX] ++ [PERF_COUNT_HW_CACHE_OP_MAX] ++ [PERF_COUNT_HW_CACHE_RESULT_MAX] = { ++[C(L1D)] = { ++ [C(OP_READ)] = { ++ [C(RESULT_ACCESS)] = 0x0040, /* Data Cache Accesses */ ++ [C(RESULT_MISS)] = 0xc860, /* L2$ access from DC Miss */ ++ }, ++ [C(OP_WRITE)] = { ++ [C(RESULT_ACCESS)] = 0, ++ [C(RESULT_MISS)] = 0, ++ }, ++ [C(OP_PREFETCH)] = { ++ [C(RESULT_ACCESS)] = 0xff5a, /* h/w prefetch DC Fills */ ++ [C(RESULT_MISS)] = 0, ++ }, ++}, ++[C(L1I)] = { ++ [C(OP_READ)] = { ++ [C(RESULT_ACCESS)] = 0x0080, /* Instruction cache fetches */ ++ [C(RESULT_MISS)] = 0x0081, /* Instruction cache misses */ ++ }, ++ [C(OP_WRITE)] = { ++ [C(RESULT_ACCESS)] = -1, ++ [C(RESULT_MISS)] = -1, ++ }, ++ [C(OP_PREFETCH)] = { ++ [C(RESULT_ACCESS)] = 0, ++ [C(RESULT_MISS)] = 0, ++ }, ++}, ++[C(LL)] = { ++ [C(OP_READ)] = { ++ [C(RESULT_ACCESS)] = 0, ++ [C(RESULT_MISS)] = 0, ++ }, ++ [C(OP_WRITE)] = { ++ [C(RESULT_ACCESS)] = 0, ++ [C(RESULT_MISS)] = 0, ++ }, ++ [C(OP_PREFETCH)] = { ++ [C(RESULT_ACCESS)] = 0, ++ [C(RESULT_MISS)] = 0, ++ }, ++}, ++[C(DTLB)] = { ++ [C(OP_READ)] = { ++ [C(RESULT_ACCESS)] = 0xff45, /* All L2 DTLB accesses */ ++ [C(RESULT_MISS)] = 0xf045, /* L2 DTLB misses (PT walks) */ ++ }, ++ [C(OP_WRITE)] = { ++ [C(RESULT_ACCESS)] = 0, ++ [C(RESULT_MISS)] = 0, ++ }, ++ [C(OP_PREFETCH)] = { ++ [C(RESULT_ACCESS)] = 0, ++ [C(RESULT_MISS)] = 0, ++ }, ++}, ++[C(ITLB)] = { ++ [C(OP_READ)] = { ++ [C(RESULT_ACCESS)] = 0x0084, /* L1 ITLB misses, L2 ITLB hits */ ++ [C(RESULT_MISS)] = 0xff85, /* L1 ITLB misses, L2 misses */ ++ }, ++ [C(OP_WRITE)] = { ++ [C(RESULT_ACCESS)] = -1, ++ [C(RESULT_MISS)] = -1, ++ }, ++ [C(OP_PREFETCH)] = { ++ [C(RESULT_ACCESS)] = -1, ++ [C(RESULT_MISS)] = -1, ++ }, ++}, ++[C(BPU)] = { ++ [C(OP_READ)] = { ++ [C(RESULT_ACCESS)] = 0x00c2, /* Retired Branch Instr. */ ++ [C(RESULT_MISS)] = 0x00c3, /* Retired Mispredicted BI */ ++ }, ++ [C(OP_WRITE)] = { ++ [C(RESULT_ACCESS)] = -1, ++ [C(RESULT_MISS)] = -1, ++ }, ++ [C(OP_PREFETCH)] = { ++ [C(RESULT_ACCESS)] = -1, ++ [C(RESULT_MISS)] = -1, ++ }, ++}, ++[C(NODE)] = { ++ [C(OP_READ)] = { ++ [C(RESULT_ACCESS)] = 0, ++ [C(RESULT_MISS)] = 0, ++ }, ++ [C(OP_WRITE)] = { ++ [C(RESULT_ACCESS)] = -1, ++ [C(RESULT_MISS)] = -1, ++ }, ++ [C(OP_PREFETCH)] = { ++ [C(RESULT_ACCESS)] = -1, ++ [C(RESULT_MISS)] = -1, ++ }, ++}, ++}; ++ + /* + * AMD Performance Monitor K7 and later, up to and including Family 16h: + */ +@@ -861,9 +965,10 @@ __init int amd_pmu_init(void) + x86_pmu.amd_nb_constraints = 0; + } + +- /* Events are common for all AMDs */ +- memcpy(hw_cache_event_ids, amd_hw_cache_event_ids, +- sizeof(hw_cache_event_ids)); ++ if (boot_cpu_data.x86 >= 0x17) ++ memcpy(hw_cache_event_ids, amd_hw_cache_event_ids_f17h, sizeof(hw_cache_event_ids)); ++ else ++ memcpy(hw_cache_event_ids, amd_hw_cache_event_ids, sizeof(hw_cache_event_ids)); + + return 0; + } +diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c +index f34d89c01edc..06f7c04a44e2 100644 +--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c ++++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c +@@ -165,6 +165,11 @@ static struct severity { + SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_DATA), + KERNEL + ), ++ MCESEV( ++ PANIC, "Instruction fetch error in kernel", ++ SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_INSTR), ++ KERNEL ++ ), + #endif + MCESEV( + PANIC, "Action required: unknown MCACOD", +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index 813cb60eb401..8dd9208ae4de 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -6789,7 +6789,8 @@ static int sev_dbg_crypt(struct kvm *kvm, struct kvm_sev_cmd *argp, bool dec) + struct page **src_p, **dst_p; + struct kvm_sev_dbg debug; + unsigned long n; +- int ret, size; ++ unsigned int size; ++ int ret; + + if (!sev_guest(kvm)) + return -ENOTTY; +@@ -6797,6 +6798,11 @@ static int sev_dbg_crypt(struct kvm *kvm, struct kvm_sev_cmd *argp, bool dec) + if (copy_from_user(&debug, (void __user *)(uintptr_t)argp->data, sizeof(debug))) + return -EFAULT; + ++ if (!debug.len || debug.src_uaddr + debug.len < debug.src_uaddr) ++ return -EINVAL; ++ if (!debug.dst_uaddr) ++ return -EINVAL; ++ + vaddr = debug.src_uaddr; + size = debug.len; + vaddr_end = vaddr + size; +@@ -6847,8 +6853,8 @@ static int sev_dbg_crypt(struct kvm *kvm, struct kvm_sev_cmd *argp, bool dec) + dst_vaddr, + len, &argp->error); + +- sev_unpin_memory(kvm, src_p, 1); +- sev_unpin_memory(kvm, dst_p, 1); ++ sev_unpin_memory(kvm, src_p, n); ++ sev_unpin_memory(kvm, dst_p, n); + + if (ret) + goto err; +diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c +index d883869437b5..fb5f29c60019 100644 +--- a/arch/x86/mm/init.c ++++ b/arch/x86/mm/init.c +@@ -6,6 +6,7 @@ + #include /* for max_low_pfn */ + #include + #include ++#include + + #include + #include +@@ -767,6 +768,11 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end) + if (debug_pagealloc_enabled()) { + pr_info("debug: unmapping init [mem %#010lx-%#010lx]\n", + begin, end - 1); ++ /* ++ * Inform kmemleak about the hole in the memory since the ++ * corresponding pages will be unmapped. ++ */ ++ kmemleak_free_part((void *)begin, end - begin); + set_memory_np(begin, (end - begin) >> PAGE_SHIFT); + } else { + /* +diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c +index 61db77b0eda9..0988971069c9 100644 +--- a/arch/x86/mm/kaslr.c ++++ b/arch/x86/mm/kaslr.c +@@ -93,7 +93,7 @@ void __init kernel_randomize_memory(void) + if (!kaslr_memory_enabled()) + return; + +- kaslr_regions[0].size_tb = 1 << (__PHYSICAL_MASK_SHIFT - TB_SHIFT); ++ kaslr_regions[0].size_tb = 1 << (MAX_PHYSMEM_BITS - TB_SHIFT); + kaslr_regions[1].size_tb = VMALLOC_SIZE_TB; + + /* +diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c +index a6d1b0241aea..a6836ab0fcc7 100644 +--- a/arch/x86/mm/tlb.c ++++ b/arch/x86/mm/tlb.c +@@ -694,7 +694,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, + { + int cpu; + +- struct flush_tlb_info info __aligned(SMP_CACHE_BYTES) = { ++ struct flush_tlb_info info = { + .mm = mm, + }; + +diff --git a/block/blk-core.c b/block/blk-core.c +index eb8b52241453..33488b1426b7 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -980,6 +980,10 @@ static void blk_rq_timed_out_timer(struct timer_list *t) + kblockd_schedule_work(&q->timeout_work); + } + ++static void blk_timeout_work_dummy(struct work_struct *work) ++{ ++} ++ + /** + * blk_alloc_queue_node - allocate a request queue + * @gfp_mask: memory allocation flags +@@ -1034,7 +1038,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id, + timer_setup(&q->backing_dev_info->laptop_mode_wb_timer, + laptop_mode_timer_fn, 0); + timer_setup(&q->timeout, blk_rq_timed_out_timer, 0); +- INIT_WORK(&q->timeout_work, NULL); ++ INIT_WORK(&q->timeout_work, blk_timeout_work_dummy); + INIT_LIST_HEAD(&q->timeout_list); + INIT_LIST_HEAD(&q->icq_list); + #ifdef CONFIG_BLK_CGROUP +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 7d53f2314d7c..414656796ecf 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -2236,7 +2236,7 @@ static int blk_mq_init_hctx(struct request_queue *q, + return 0; + + free_fq: +- kfree(hctx->fq); ++ blk_free_flush_queue(hctx->fq); + exit_hctx: + if (set->ops->exit_hctx) + set->ops->exit_hctx(hctx, hctx_idx); +diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c +index c24589414c75..0f36db0cf74a 100644 +--- a/drivers/block/xsysace.c ++++ b/drivers/block/xsysace.c +@@ -1063,6 +1063,8 @@ static int ace_setup(struct ace_device *ace) + return 0; + + err_read: ++ /* prevent double queue cleanup */ ++ ace->gd->queue = NULL; + put_disk(ace->gd); + err_alloc_disk: + blk_cleanup_queue(ace->queue); +diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c +index 4593baff2bc9..19eecf198321 100644 +--- a/drivers/bluetooth/btmtkuart.c ++++ b/drivers/bluetooth/btmtkuart.c +@@ -115,11 +115,13 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, u8 op, u8 flag, u16 plen, + TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT); + if (err == -EINTR) { + bt_dev_err(hdev, "Execution of wmt command interrupted"); ++ clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); + return err; + } + + if (err) { + bt_dev_err(hdev, "Execution of wmt command timed out"); ++ clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); + return -ETIMEDOUT; + } + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 77b67a5f21ee..40a4f95f6178 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2888,6 +2888,7 @@ static int btusb_config_oob_wake(struct hci_dev *hdev) + return 0; + } + ++ irq_set_status_flags(irq, IRQ_NOAUTOEN); + ret = devm_request_irq(&hdev->dev, irq, btusb_oob_wake_handler, + 0, "OOB Wake-on-BT", data); + if (ret) { +@@ -2902,7 +2903,6 @@ static int btusb_config_oob_wake(struct hci_dev *hdev) + } + + data->oob_wake_irq = irq; +- disable_irq(irq); + bt_dev_info(hdev, "OOB Wake-on-BT configured at IRQ %u", irq); + return 0; + } +diff --git a/drivers/clk/qcom/gcc-msm8998.c b/drivers/clk/qcom/gcc-msm8998.c +index 9f0ae403d5f5..cd937ce6aaaf 100644 +--- a/drivers/clk/qcom/gcc-msm8998.c ++++ b/drivers/clk/qcom/gcc-msm8998.c +@@ -1101,6 +1101,7 @@ static struct clk_rcg2 ufs_axi_clk_src = { + + static const struct freq_tbl ftbl_usb30_master_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), ++ F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0), + F(120000000, P_GPLL0_OUT_MAIN, 5, 0, 0), + F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0), + { } +diff --git a/drivers/clk/x86/clk-pmc-atom.c b/drivers/clk/x86/clk-pmc-atom.c +index d977193842df..19174835693b 100644 +--- a/drivers/clk/x86/clk-pmc-atom.c ++++ b/drivers/clk/x86/clk-pmc-atom.c +@@ -165,7 +165,7 @@ static const struct clk_ops plt_clk_ops = { + }; + + static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id, +- void __iomem *base, ++ const struct pmc_clk_data *pmc_data, + const char **parent_names, + int num_parents) + { +@@ -184,9 +184,17 @@ static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id, + init.num_parents = num_parents; + + pclk->hw.init = &init; +- pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE; ++ pclk->reg = pmc_data->base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE; + spin_lock_init(&pclk->lock); + ++ /* ++ * On some systems, the pmc_plt_clocks already enabled by the ++ * firmware are being marked as critical to avoid them being ++ * gated by the clock framework. ++ */ ++ if (pmc_data->critical && plt_clk_is_enabled(&pclk->hw)) ++ init.flags |= CLK_IS_CRITICAL; ++ + ret = devm_clk_hw_register(&pdev->dev, &pclk->hw); + if (ret) { + pclk = ERR_PTR(ret); +@@ -332,7 +340,7 @@ static int plt_clk_probe(struct platform_device *pdev) + return PTR_ERR(parent_names); + + for (i = 0; i < PMC_CLK_NUM; i++) { +- data->clks[i] = plt_clk_register(pdev, i, pmc_data->base, ++ data->clks[i] = plt_clk_register(pdev, i, pmc_data, + parent_names, data->nparents); + if (IS_ERR(data->clks[i])) { + err = PTR_ERR(data->clks[i]); +diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c +index b0aeffd4e269..1606abead22c 100644 +--- a/drivers/firmware/efi/runtime-wrappers.c ++++ b/drivers/firmware/efi/runtime-wrappers.c +@@ -95,7 +95,7 @@ struct efi_runtime_work { + efi_rts_work.status = EFI_ABORTED; \ + \ + init_completion(&efi_rts_work.efi_rts_comp); \ +- INIT_WORK_ONSTACK(&efi_rts_work.work, efi_call_rts); \ ++ INIT_WORK(&efi_rts_work.work, efi_call_rts); \ + efi_rts_work.arg1 = _arg1; \ + efi_rts_work.arg2 = _arg2; \ + efi_rts_work.arg3 = _arg3; \ +diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c +index 2d1dfa1e0745..e86e61dda4b7 100644 +--- a/drivers/gpio/gpio-mxc.c ++++ b/drivers/gpio/gpio-mxc.c +@@ -438,8 +438,11 @@ static int mxc_gpio_probe(struct platform_device *pdev) + + /* the controller clock is optional */ + port->clk = devm_clk_get(&pdev->dev, NULL); +- if (IS_ERR(port->clk)) ++ if (IS_ERR(port->clk)) { ++ if (PTR_ERR(port->clk) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; + port->clk = NULL; ++ } + + err = clk_prepare_enable(port->clk); + if (err) { +diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c +index ebc9ffde41e9..a353a011fbdf 100644 +--- a/drivers/hid/hid-debug.c ++++ b/drivers/hid/hid-debug.c +@@ -1060,10 +1060,15 @@ static int hid_debug_rdesc_show(struct seq_file *f, void *p) + seq_printf(f, "\n\n"); + + /* dump parsed data and input mappings */ ++ if (down_interruptible(&hdev->driver_input_lock)) ++ return 0; ++ + hid_dump_device(hdev, f); + seq_printf(f, "\n"); + hid_dump_input_mapping(hdev, f); + ++ up(&hdev->driver_input_lock); ++ + return 0; + } + +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index a3916e58dbf5..e649940e065d 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -982,6 +982,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + case 0x1b8: map_key_clear(KEY_VIDEO); break; + case 0x1bc: map_key_clear(KEY_MESSENGER); break; + case 0x1bd: map_key_clear(KEY_INFO); break; ++ case 0x1cb: map_key_clear(KEY_ASSISTANT); break; + case 0x201: map_key_clear(KEY_NEW); break; + case 0x202: map_key_clear(KEY_OPEN); break; + case 0x203: map_key_clear(KEY_CLOSE); break; +diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c +index 19cc980eebce..8425d3548a41 100644 +--- a/drivers/hid/hid-logitech-hidpp.c ++++ b/drivers/hid/hid-logitech-hidpp.c +@@ -1907,6 +1907,13 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) + kfree(data); + return -ENOMEM; + } ++ data->wq = create_singlethread_workqueue("hidpp-ff-sendqueue"); ++ if (!data->wq) { ++ kfree(data->effect_ids); ++ kfree(data); ++ return -ENOMEM; ++ } ++ + data->hidpp = hidpp; + data->feature_index = feature_index; + data->version = version; +@@ -1951,7 +1958,6 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) + /* ignore boost value at response.fap.params[2] */ + + /* init the hardware command queue */ +- data->wq = create_singlethread_workqueue("hidpp-ff-sendqueue"); + atomic_set(&data->workqueue_size, 0); + + /* initialize with zero autocenter to get wheel in usable state */ +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index 94088c0ed68a..e24790c988c0 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -744,7 +744,6 @@ static const struct hid_device_id hid_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, +- { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0400) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, +@@ -1025,6 +1024,10 @@ bool hid_ignore(struct hid_device *hdev) + if (hdev->product == 0x0401 && + strncmp(hdev->name, "ELAN0800", 8) != 0) + return true; ++ /* Same with product id 0x0400 */ ++ if (hdev->product == 0x0400 && ++ strncmp(hdev->name, "QTEC0001", 8) != 0) ++ return true; + break; + } + +diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c +index c406700789e1..7bd409eaf0ac 100644 +--- a/drivers/i2c/busses/i2c-imx.c ++++ b/drivers/i2c/busses/i2c-imx.c +@@ -510,9 +510,9 @@ static int i2c_imx_clk_notifier_call(struct notifier_block *nb, + unsigned long action, void *data) + { + struct clk_notifier_data *ndata = data; +- struct imx_i2c_struct *i2c_imx = container_of(&ndata->clk, ++ struct imx_i2c_struct *i2c_imx = container_of(nb, + struct imx_i2c_struct, +- clk); ++ clk_change_nb); + + if (action & POST_RATE_CHANGE) + i2c_imx_set_clk(i2c_imx, ndata->new_rate); +diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c +index 62d023e737d9..a492da9fd0d3 100644 +--- a/drivers/i2c/busses/i2c-stm32f7.c ++++ b/drivers/i2c/busses/i2c-stm32f7.c +@@ -424,7 +424,7 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, + STM32F7_I2C_ANALOG_FILTER_DELAY_MAX : 0); + dnf_delay = setup->dnf * i2cclk; + +- sdadel_min = setup->fall_time - i2c_specs[setup->speed].hddat_min - ++ sdadel_min = i2c_specs[setup->speed].hddat_min + setup->fall_time - + af_delay_min - (setup->dnf + 3) * i2cclk; + + sdadel_max = i2c_specs[setup->speed].vddat_max - setup->rise_time - +diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c +index 915f5edbab33..e6c554e6ba58 100644 +--- a/drivers/i2c/busses/i2c-synquacer.c ++++ b/drivers/i2c/busses/i2c-synquacer.c +@@ -602,6 +602,8 @@ static int synquacer_i2c_probe(struct platform_device *pdev) + i2c->adapter = synquacer_i2c_ops; + i2c_set_adapdata(&i2c->adapter, i2c); + i2c->adapter.dev.parent = &pdev->dev; ++ i2c->adapter.dev.of_node = pdev->dev.of_node; ++ ACPI_COMPANION_SET(&i2c->adapter.dev, ACPI_COMPANION(&pdev->dev)); + i2c->adapter.nr = pdev->id; + init_completion(&i2c->completion); + +diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c +index 9200e349f29e..5b0e1d9e5adc 100644 +--- a/drivers/i2c/i2c-core-base.c ++++ b/drivers/i2c/i2c-core-base.c +@@ -306,10 +306,7 @@ static int i2c_smbus_host_notify_to_irq(const struct i2c_client *client) + if (client->flags & I2C_CLIENT_TEN) + return -EINVAL; + +- irq = irq_find_mapping(adap->host_notify_domain, client->addr); +- if (!irq) +- irq = irq_create_mapping(adap->host_notify_domain, +- client->addr); ++ irq = irq_create_mapping(adap->host_notify_domain, client->addr); + + return irq > 0 ? irq : -ENXIO; + } +@@ -330,6 +327,8 @@ static int i2c_device_probe(struct device *dev) + + if (client->flags & I2C_CLIENT_HOST_NOTIFY) { + dev_dbg(dev, "Using Host Notify IRQ\n"); ++ /* Keep adapter active when Host Notify is required */ ++ pm_runtime_get_sync(&client->adapter->dev); + irq = i2c_smbus_host_notify_to_irq(client); + } else if (dev->of_node) { + irq = of_irq_get_byname(dev->of_node, "irq"); +@@ -433,6 +432,10 @@ static int i2c_device_remove(struct device *dev) + dev_pm_clear_wake_irq(&client->dev); + device_init_wakeup(&client->dev, false); + ++ client->irq = client->init_irq; ++ if (client->flags & I2C_CLIENT_HOST_NOTIFY) ++ pm_runtime_put(&client->adapter->dev); ++ + return status; + } + +@@ -742,10 +745,11 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) + client->flags = info->flags; + client->addr = info->addr; + +- client->irq = info->irq; +- if (!client->irq) +- client->irq = i2c_dev_irq_from_resources(info->resources, ++ client->init_irq = info->irq; ++ if (!client->init_irq) ++ client->init_irq = i2c_dev_irq_from_resources(info->resources, + info->num_resources); ++ client->irq = client->init_irq; + + strlcpy(client->name, info->type, sizeof(client->name)); + +diff --git a/drivers/infiniband/core/security.c b/drivers/infiniband/core/security.c +index 9b0bea8303e0..b79b61bd6ee4 100644 +--- a/drivers/infiniband/core/security.c ++++ b/drivers/infiniband/core/security.c +@@ -711,16 +711,20 @@ int ib_mad_agent_security_setup(struct ib_mad_agent *agent, + agent->device->name, + agent->port_num); + if (ret) +- return ret; ++ goto free_security; + + agent->lsm_nb.notifier_call = ib_mad_agent_security_change; + ret = register_lsm_notifier(&agent->lsm_nb); + if (ret) +- return ret; ++ goto free_security; + + agent->smp_allowed = true; + agent->lsm_nb_reg = true; + return 0; ++ ++free_security: ++ security_ib_free_security(agent->security); ++ return ret; + } + + void ib_mad_agent_security_cleanup(struct ib_mad_agent *agent) +@@ -728,9 +732,10 @@ void ib_mad_agent_security_cleanup(struct ib_mad_agent *agent) + if (!rdma_protocol_ib(agent->device, agent->port_num)) + return; + +- security_ib_free_security(agent->security); + if (agent->lsm_nb_reg) + unregister_lsm_notifier(&agent->lsm_nb); ++ ++ security_ib_free_security(agent->security); + } + + int ib_mad_enforce_security(struct ib_mad_agent_private *map, u16 pkey_index) +diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c +index 6ee03d6089eb..82f309fb3ce5 100644 +--- a/drivers/infiniband/core/verbs.c ++++ b/drivers/infiniband/core/verbs.c +@@ -1087,8 +1087,8 @@ struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd, + } + EXPORT_SYMBOL(ib_open_qp); + +-static struct ib_qp *ib_create_xrc_qp(struct ib_qp *qp, +- struct ib_qp_init_attr *qp_init_attr) ++static struct ib_qp *create_xrc_qp(struct ib_qp *qp, ++ struct ib_qp_init_attr *qp_init_attr) + { + struct ib_qp *real_qp = qp; + +@@ -1103,10 +1103,10 @@ static struct ib_qp *ib_create_xrc_qp(struct ib_qp *qp, + + qp = __ib_open_qp(real_qp, qp_init_attr->event_handler, + qp_init_attr->qp_context); +- if (!IS_ERR(qp)) +- __ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp); +- else +- real_qp->device->destroy_qp(real_qp); ++ if (IS_ERR(qp)) ++ return qp; ++ ++ __ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp); + return qp; + } + +@@ -1137,10 +1137,8 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd, + return qp; + + ret = ib_create_qp_security(qp, device); +- if (ret) { +- ib_destroy_qp(qp); +- return ERR_PTR(ret); +- } ++ if (ret) ++ goto err; + + qp->real_qp = qp; + qp->qp_type = qp_init_attr->qp_type; +@@ -1153,8 +1151,15 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd, + INIT_LIST_HEAD(&qp->sig_mrs); + qp->port = 0; + +- if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) +- return ib_create_xrc_qp(qp, qp_init_attr); ++ if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) { ++ struct ib_qp *xrc_qp = create_xrc_qp(qp, qp_init_attr); ++ ++ if (IS_ERR(xrc_qp)) { ++ ret = PTR_ERR(xrc_qp); ++ goto err; ++ } ++ return xrc_qp; ++ } + + qp->event_handler = qp_init_attr->event_handler; + qp->qp_context = qp_init_attr->qp_context; +@@ -1181,11 +1186,8 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd, + + if (qp_init_attr->cap.max_rdma_ctxs) { + ret = rdma_rw_init_mrs(qp, qp_init_attr); +- if (ret) { +- pr_err("failed to init MR pool ret= %d\n", ret); +- ib_destroy_qp(qp); +- return ERR_PTR(ret); +- } ++ if (ret) ++ goto err; + } + + /* +@@ -1198,6 +1200,11 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd, + device->attrs.max_sge_rd); + + return qp; ++ ++err: ++ ib_destroy_qp(qp); ++ return ERR_PTR(ret); ++ + } + EXPORT_SYMBOL(ib_create_qp); + +diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c +index f4bce5aa0ff8..ea4afdeb06a4 100644 +--- a/drivers/infiniband/ulp/srpt/ib_srpt.c ++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c +@@ -2793,8 +2793,19 @@ static void srpt_queue_tm_rsp(struct se_cmd *cmd) + srpt_queue_response(cmd); + } + ++/* ++ * This function is called for aborted commands if no response is sent to the ++ * initiator. Make sure that the credits freed by aborting a command are ++ * returned to the initiator the next time a response is sent by incrementing ++ * ch->req_lim_delta. ++ */ + static void srpt_aborted_task(struct se_cmd *cmd) + { ++ struct srpt_send_ioctx *ioctx = container_of(cmd, ++ struct srpt_send_ioctx, cmd); ++ struct srpt_rdma_ch *ch = ioctx->ch; ++ ++ atomic_inc(&ch->req_lim_delta); + } + + static int srpt_queue_status(struct se_cmd *cmd) +diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c +index effb63205d3d..4c67cf30a5d9 100644 +--- a/drivers/input/keyboard/snvs_pwrkey.c ++++ b/drivers/input/keyboard/snvs_pwrkey.c +@@ -148,6 +148,9 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) + return error; + } + ++ pdata->input = input; ++ platform_set_drvdata(pdev, pdata); ++ + error = devm_request_irq(&pdev->dev, pdata->irq, + imx_snvs_pwrkey_interrupt, + 0, pdev->name, pdev); +@@ -163,9 +166,6 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) + return error; + } + +- pdata->input = input; +- platform_set_drvdata(pdev, pdata); +- + device_init_wakeup(&pdev->dev, pdata->wakeup); + + return 0; +diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c +index 704e99046916..b6f95f20f924 100644 +--- a/drivers/input/touchscreen/stmfts.c ++++ b/drivers/input/touchscreen/stmfts.c +@@ -106,27 +106,29 @@ struct stmfts_data { + bool running; + }; + +-static void stmfts_brightness_set(struct led_classdev *led_cdev, ++static int stmfts_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value) + { + struct stmfts_data *sdata = container_of(led_cdev, + struct stmfts_data, led_cdev); + int err; + +- if (value == sdata->led_status || !sdata->ledvdd) +- return; +- +- if (!value) { +- regulator_disable(sdata->ledvdd); +- } else { +- err = regulator_enable(sdata->ledvdd); +- if (err) +- dev_warn(&sdata->client->dev, +- "failed to disable ledvdd regulator: %d\n", +- err); ++ if (value != sdata->led_status && sdata->ledvdd) { ++ if (!value) { ++ regulator_disable(sdata->ledvdd); ++ } else { ++ err = regulator_enable(sdata->ledvdd); ++ if (err) { ++ dev_warn(&sdata->client->dev, ++ "failed to disable ledvdd regulator: %d\n", ++ err); ++ return err; ++ } ++ } ++ sdata->led_status = value; + } + +- sdata->led_status = value; ++ return 0; + } + + static enum led_brightness stmfts_brightness_get(struct led_classdev *led_cdev) +@@ -608,7 +610,7 @@ static int stmfts_enable_led(struct stmfts_data *sdata) + sdata->led_cdev.name = STMFTS_DEV_NAME; + sdata->led_cdev.max_brightness = LED_ON; + sdata->led_cdev.brightness = LED_OFF; +- sdata->led_cdev.brightness_set = stmfts_brightness_set; ++ sdata->led_cdev.brightness_set_blocking = stmfts_brightness_set; + sdata->led_cdev.brightness_get = stmfts_brightness_get; + + err = devm_led_classdev_register(&sdata->client->dev, &sdata->led_cdev); +diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c +index 64d1402882c8..1f71c14c8aab 100644 +--- a/drivers/media/i2c/ov7670.c ++++ b/drivers/media/i2c/ov7670.c +@@ -159,10 +159,10 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); + #define REG_GFIX 0x69 /* Fix gain control */ + + #define REG_DBLV 0x6b /* PLL control an debugging */ +-#define DBLV_BYPASS 0x00 /* Bypass PLL */ +-#define DBLV_X4 0x01 /* clock x4 */ +-#define DBLV_X6 0x10 /* clock x6 */ +-#define DBLV_X8 0x11 /* clock x8 */ ++#define DBLV_BYPASS 0x0a /* Bypass PLL */ ++#define DBLV_X4 0x4a /* clock x4 */ ++#define DBLV_X6 0x8a /* clock x6 */ ++#define DBLV_X8 0xca /* clock x8 */ + + #define REG_SCALING_XSC 0x70 /* Test pattern and horizontal scale factor */ + #define TEST_PATTTERN_0 0x80 +@@ -862,7 +862,7 @@ static int ov7675_set_framerate(struct v4l2_subdev *sd, + if (ret < 0) + return ret; + +- return ov7670_write(sd, REG_DBLV, DBLV_X4); ++ return 0; + } + + static void ov7670_get_framerate_legacy(struct v4l2_subdev *sd, +@@ -1797,11 +1797,7 @@ static int ov7670_probe(struct i2c_client *client, + if (config->clock_speed) + info->clock_speed = config->clock_speed; + +- /* +- * It should be allowed for ov7670 too when it is migrated to +- * the new frame rate formula. +- */ +- if (config->pll_bypass && id->driver_data != MODEL_OV7670) ++ if (config->pll_bypass) + info->pll_bypass = true; + + if (config->pclk_hb_disable) +diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c +index 299016bc46d9..104477b512a2 100644 +--- a/drivers/mfd/twl-core.c ++++ b/drivers/mfd/twl-core.c +@@ -1245,6 +1245,28 @@ free: + return status; + } + ++static int __maybe_unused twl_suspend(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ if (client->irq) ++ disable_irq(client->irq); ++ ++ return 0; ++} ++ ++static int __maybe_unused twl_resume(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ if (client->irq) ++ enable_irq(client->irq); ++ ++ return 0; ++} ++ ++static SIMPLE_DEV_PM_OPS(twl_dev_pm_ops, twl_suspend, twl_resume); ++ + static const struct i2c_device_id twl_ids[] = { + { "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */ + { "twl5030", 0 }, /* T2 updated */ +@@ -1262,6 +1284,7 @@ static const struct i2c_device_id twl_ids[] = { + /* One Client Driver , 4 Clients */ + static struct i2c_driver twl_driver = { + .driver.name = DRIVER_NAME, ++ .driver.pm = &twl_dev_pm_ops, + .id_table = twl_ids, + .probe = twl_probe, + .remove = twl_remove, +diff --git a/drivers/net/bonding/bond_sysfs_slave.c b/drivers/net/bonding/bond_sysfs_slave.c +index 2f120b2ffef0..4985268e2273 100644 +--- a/drivers/net/bonding/bond_sysfs_slave.c ++++ b/drivers/net/bonding/bond_sysfs_slave.c +@@ -55,7 +55,9 @@ static SLAVE_ATTR_RO(link_failure_count); + + static ssize_t perm_hwaddr_show(struct slave *slave, char *buf) + { +- return sprintf(buf, "%pM\n", slave->perm_hwaddr); ++ return sprintf(buf, "%*phC\n", ++ slave->dev->addr_len, ++ slave->perm_hwaddr); + } + static SLAVE_ATTR_RO(perm_hwaddr); + +diff --git a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c +index 74849be5f004..e2919005ead3 100644 +--- a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c ++++ b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c +@@ -354,7 +354,10 @@ static struct cxgbi_ppm_pool *ppm_alloc_cpu_pool(unsigned int *total, + ppmax = max; + + /* pool size must be multiple of unsigned long */ +- bmap = BITS_TO_LONGS(ppmax); ++ bmap = ppmax / BITS_PER_TYPE(unsigned long); ++ if (!bmap) ++ return NULL; ++ + ppmax = (bmap * sizeof(unsigned long)) << 3; + + alloc_sz = sizeof(*pools) + sizeof(unsigned long) * bmap; +@@ -402,6 +405,10 @@ int cxgbi_ppm_init(void **ppm_pp, struct net_device *ndev, + if (reserve_factor) { + ppmax_pool = ppmax / reserve_factor; + pool = ppm_alloc_cpu_pool(&ppmax_pool, &pool_index_max); ++ if (!pool) { ++ ppmax_pool = 0; ++ reserve_factor = 0; ++ } + + pr_debug("%s: ppmax %u, cpu total %u, per cpu %u.\n", + ndev->name, ppmax, ppmax_pool, pool_index_max); +diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c +index 79d03f8ee7b1..c7fa97a7e1f4 100644 +--- a/drivers/net/ethernet/hisilicon/hns/hnae.c ++++ b/drivers/net/ethernet/hisilicon/hns/hnae.c +@@ -150,7 +150,6 @@ out_buffer_fail: + /* free desc along with its attached buffer */ + static void hnae_free_desc(struct hnae_ring *ring) + { +- hnae_free_buffers(ring); + dma_unmap_single(ring_to_dev(ring), ring->desc_dma_addr, + ring->desc_num * sizeof(ring->desc[0]), + ring_to_dma_dir(ring)); +@@ -183,6 +182,9 @@ static int hnae_alloc_desc(struct hnae_ring *ring) + /* fini ring, also free the buffer for the ring */ + static void hnae_fini_ring(struct hnae_ring *ring) + { ++ if (is_rx_ring(ring)) ++ hnae_free_buffers(ring); ++ + hnae_free_desc(ring); + kfree(ring->desc_cb); + ring->desc_cb = NULL; +diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +index b8155f5e71b4..fdff5526d2e8 100644 +--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c ++++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +@@ -2750,6 +2750,17 @@ int hns_dsaf_get_regs_count(void) + return DSAF_DUMP_REGS_NUM; + } + ++static int hns_dsaf_get_port_id(u8 port) ++{ ++ if (port < DSAF_SERVICE_NW_NUM) ++ return port; ++ ++ if (port >= DSAF_BASE_INNER_PORT_NUM) ++ return port - DSAF_BASE_INNER_PORT_NUM + DSAF_SERVICE_NW_NUM; ++ ++ return -EINVAL; ++} ++ + static void set_promisc_tcam_enable(struct dsaf_device *dsaf_dev, u32 port) + { + struct dsaf_tbl_tcam_ucast_cfg tbl_tcam_ucast = {0, 1, 0, 0, 0x80}; +@@ -2815,23 +2826,33 @@ static void set_promisc_tcam_enable(struct dsaf_device *dsaf_dev, u32 port) + memset(&temp_key, 0x0, sizeof(temp_key)); + mask_entry.addr[0] = 0x01; + hns_dsaf_set_mac_key(dsaf_dev, &mask_key, mask_entry.in_vlan_id, +- port, mask_entry.addr); ++ 0xf, mask_entry.addr); + tbl_tcam_mcast.tbl_mcast_item_vld = 1; + tbl_tcam_mcast.tbl_mcast_old_en = 0; + +- if (port < DSAF_SERVICE_NW_NUM) { +- mskid = port; +- } else if (port >= DSAF_BASE_INNER_PORT_NUM) { +- mskid = port - DSAF_BASE_INNER_PORT_NUM + DSAF_SERVICE_NW_NUM; +- } else { ++ /* set MAC port to handle multicast */ ++ mskid = hns_dsaf_get_port_id(port); ++ if (mskid == -EINVAL) { + dev_err(dsaf_dev->dev, "%s,pnum(%d)error,key(%#x:%#x)\n", + dsaf_dev->ae_dev.name, port, + mask_key.high.val, mask_key.low.val); + return; + } ++ dsaf_set_bit(tbl_tcam_mcast.tbl_mcast_port_msk[mskid / 32], ++ mskid % 32, 1); + ++ /* set pool bit map to handle multicast */ ++ mskid = hns_dsaf_get_port_id(port_num); ++ if (mskid == -EINVAL) { ++ dev_err(dsaf_dev->dev, ++ "%s, pool bit map pnum(%d)error,key(%#x:%#x)\n", ++ dsaf_dev->ae_dev.name, port_num, ++ mask_key.high.val, mask_key.low.val); ++ return; ++ } + dsaf_set_bit(tbl_tcam_mcast.tbl_mcast_port_msk[mskid / 32], + mskid % 32, 1); ++ + memcpy(&temp_key, &mask_key, sizeof(mask_key)); + hns_dsaf_tcam_mc_cfg_vague(dsaf_dev, entry_index, &tbl_tcam_data_mc, + (struct dsaf_tbl_tcam_data *)(&mask_key), +diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c +index ba4316910dea..a60f207768fc 100644 +--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c ++++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c +@@ -129,7 +129,7 @@ static void hns_xgmac_lf_rf_control_init(struct mac_driver *mac_drv) + dsaf_set_bit(val, XGMAC_UNIDIR_EN_B, 0); + dsaf_set_bit(val, XGMAC_RF_TX_EN_B, 1); + dsaf_set_field(val, XGMAC_LF_RF_INSERT_M, XGMAC_LF_RF_INSERT_S, 0); +- dsaf_write_reg(mac_drv, XGMAC_MAC_TX_LF_RF_CONTROL_REG, val); ++ dsaf_write_dev(mac_drv, XGMAC_MAC_TX_LF_RF_CONTROL_REG, val); + } + + /** +diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c +index cc84133c184d..1c70f9aa0aa7 100644 +--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c +@@ -29,9 +29,6 @@ + + #define SERVICE_TIMER_HZ (1 * HZ) + +-#define NIC_TX_CLEAN_MAX_NUM 256 +-#define NIC_RX_CLEAN_MAX_NUM 64 +- + #define RCB_IRQ_NOT_INITED 0 + #define RCB_IRQ_INITED 1 + #define HNS_BUFFER_SIZE_2048 2048 +@@ -376,8 +373,6 @@ netdev_tx_t hns_nic_net_xmit_hw(struct net_device *ndev, + wmb(); /* commit all data before submit */ + assert(skb->queue_mapping < priv->ae_handle->q_num); + hnae_queue_xmit(priv->ae_handle->qs[skb->queue_mapping], buf_num); +- ring->stats.tx_pkts++; +- ring->stats.tx_bytes += skb->len; + + return NETDEV_TX_OK; + +@@ -999,6 +994,9 @@ static int hns_nic_tx_poll_one(struct hns_nic_ring_data *ring_data, + /* issue prefetch for next Tx descriptor */ + prefetch(&ring->desc_cb[ring->next_to_clean]); + } ++ /* update tx ring statistics. */ ++ ring->stats.tx_pkts += pkts; ++ ring->stats.tx_bytes += bytes; + + NETIF_TX_UNLOCK(ring); + +@@ -2150,7 +2148,7 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv) + hns_nic_tx_fini_pro_v2; + + netif_napi_add(priv->netdev, &rd->napi, +- hns_nic_common_poll, NIC_TX_CLEAN_MAX_NUM); ++ hns_nic_common_poll, NAPI_POLL_WEIGHT); + rd->ring->irq_init_flag = RCB_IRQ_NOT_INITED; + } + for (i = h->q_num; i < h->q_num * 2; i++) { +@@ -2163,7 +2161,7 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv) + hns_nic_rx_fini_pro_v2; + + netif_napi_add(priv->netdev, &rd->napi, +- hns_nic_common_poll, NIC_RX_CLEAN_MAX_NUM); ++ hns_nic_common_poll, NAPI_POLL_WEIGHT); + rd->ring->irq_init_flag = RCB_IRQ_NOT_INITED; + } + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile +index cb8ddd043476..d278fc7ea3ed 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile +@@ -3,7 +3,7 @@ + # Makefile for the HISILICON network device drivers. + # + +-ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3 ++ccflags-y := -I $(srctree)/drivers/net/ethernet/hisilicon/hns3 + + obj-$(CONFIG_HNS3_HCLGE) += hclge.o + hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o hclge_mbx.o +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/Makefile b/drivers/net/ethernet/hisilicon/hns3/hns3vf/Makefile +index fb93bbd35845..6193f8fa7cf3 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/Makefile ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/Makefile +@@ -3,7 +3,7 @@ + # Makefile for the HISILICON network device drivers. + # + +-ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3 ++ccflags-y := -I $(srctree)/drivers/net/ethernet/hisilicon/hns3 + + obj-$(CONFIG_HNS3_HCLGEVF) += hclgevf.o + hclgevf-objs = hclgevf_main.o hclgevf_cmd.o hclgevf_mbx.o +\ No newline at end of file +diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h +index 8a28f3388f69..dca671591ef6 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_defines.h ++++ b/drivers/net/ethernet/intel/igb/e1000_defines.h +@@ -194,6 +194,8 @@ + /* enable link status from external LINK_0 and LINK_1 pins */ + #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ + #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ ++#define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */ ++#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 /* PHY PM enable */ + #define E1000_CTRL_SDP0_DIR 0x00400000 /* SDP0 Data direction */ + #define E1000_CTRL_SDP1_DIR 0x00800000 /* SDP1 Data direction */ + #define E1000_CTRL_RST 0x04000000 /* Global reset */ +diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c +index ffaa6e031632..aa39a068858e 100644 +--- a/drivers/net/ethernet/intel/igb/igb_main.c ++++ b/drivers/net/ethernet/intel/igb/igb_main.c +@@ -8754,9 +8754,7 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, + struct e1000_hw *hw = &adapter->hw; + u32 ctrl, rctl, status; + u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol; +-#ifdef CONFIG_PM +- int retval = 0; +-#endif ++ bool wake; + + rtnl_lock(); + netif_device_detach(netdev); +@@ -8769,14 +8767,6 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, + igb_clear_interrupt_scheme(adapter); + rtnl_unlock(); + +-#ifdef CONFIG_PM +- if (!runtime) { +- retval = pci_save_state(pdev); +- if (retval) +- return retval; +- } +-#endif +- + status = rd32(E1000_STATUS); + if (status & E1000_STATUS_LU) + wufc &= ~E1000_WUFC_LNKC; +@@ -8793,10 +8783,6 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, + } + + ctrl = rd32(E1000_CTRL); +- /* advertise wake from D3Cold */ +- #define E1000_CTRL_ADVD3WUC 0x00100000 +- /* phy power management enable */ +- #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 + ctrl |= E1000_CTRL_ADVD3WUC; + wr32(E1000_CTRL, ctrl); + +@@ -8810,12 +8796,15 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, + wr32(E1000_WUFC, 0); + } + +- *enable_wake = wufc || adapter->en_mng_pt; +- if (!*enable_wake) ++ wake = wufc || adapter->en_mng_pt; ++ if (!wake) + igb_power_down_link(adapter); + else + igb_power_up_link(adapter); + ++ if (enable_wake) ++ *enable_wake = wake; ++ + /* Release control of h/w to f/w. If f/w is AMT enabled, this + * would have already happened in close and is redundant. + */ +@@ -8858,22 +8847,7 @@ static void igb_deliver_wake_packet(struct net_device *netdev) + + static int __maybe_unused igb_suspend(struct device *dev) + { +- int retval; +- bool wake; +- struct pci_dev *pdev = to_pci_dev(dev); +- +- retval = __igb_shutdown(pdev, &wake, 0); +- if (retval) +- return retval; +- +- if (wake) { +- pci_prepare_to_sleep(pdev); +- } else { +- pci_wake_from_d3(pdev, false); +- pci_set_power_state(pdev, PCI_D3hot); +- } +- +- return 0; ++ return __igb_shutdown(to_pci_dev(dev), NULL, 0); + } + + static int __maybe_unused igb_resume(struct device *dev) +@@ -8944,22 +8918,7 @@ static int __maybe_unused igb_runtime_idle(struct device *dev) + + static int __maybe_unused igb_runtime_suspend(struct device *dev) + { +- struct pci_dev *pdev = to_pci_dev(dev); +- int retval; +- bool wake; +- +- retval = __igb_shutdown(pdev, &wake, 1); +- if (retval) +- return retval; +- +- if (wake) { +- pci_prepare_to_sleep(pdev); +- } else { +- pci_wake_from_d3(pdev, false); +- pci_set_power_state(pdev, PCI_D3hot); +- } +- +- return 0; ++ return __igb_shutdown(to_pci_dev(dev), NULL, 1); + } + + static int __maybe_unused igb_runtime_resume(struct device *dev) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +index 26c9f9421901..55ccd90beeb0 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +@@ -80,8 +80,7 @@ static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport, + opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); + MLX5_SET(modify_nic_vport_context_in, in, field_select.change_event, 1); + MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); +- if (vport) +- MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); ++ MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); + nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, + in, nic_vport_context); + +@@ -109,8 +108,7 @@ static int modify_esw_vport_context_cmd(struct mlx5_core_dev *dev, u16 vport, + MLX5_SET(modify_esw_vport_context_in, in, opcode, + MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT); + MLX5_SET(modify_esw_vport_context_in, in, vport_number, vport); +- if (vport) +- MLX5_SET(modify_esw_vport_context_in, in, other_vport, 1); ++ MLX5_SET(modify_esw_vport_context_in, in, other_vport, 1); + return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); + } + +diff --git a/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/drivers/net/ethernet/stmicro/stmmac/descs_com.h +index 40d6356a7e73..3dfb07a78952 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h ++++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h +@@ -29,11 +29,13 @@ + /* Specific functions used for Ring mode */ + + /* Enhanced descriptors */ +-static inline void ehn_desc_rx_set_on_ring(struct dma_desc *p, int end) ++static inline void ehn_desc_rx_set_on_ring(struct dma_desc *p, int end, ++ int bfsize) + { +- p->des1 |= cpu_to_le32((BUF_SIZE_8KiB +- << ERDES1_BUFFER2_SIZE_SHIFT) +- & ERDES1_BUFFER2_SIZE_MASK); ++ if (bfsize == BUF_SIZE_16KiB) ++ p->des1 |= cpu_to_le32((BUF_SIZE_8KiB ++ << ERDES1_BUFFER2_SIZE_SHIFT) ++ & ERDES1_BUFFER2_SIZE_MASK); + + if (end) + p->des1 |= cpu_to_le32(ERDES1_END_RING); +@@ -59,11 +61,15 @@ static inline void enh_set_tx_desc_len_on_ring(struct dma_desc *p, int len) + } + + /* Normal descriptors */ +-static inline void ndesc_rx_set_on_ring(struct dma_desc *p, int end) ++static inline void ndesc_rx_set_on_ring(struct dma_desc *p, int end, int bfsize) + { +- p->des1 |= cpu_to_le32(((BUF_SIZE_2KiB - 1) +- << RDES1_BUFFER2_SIZE_SHIFT) +- & RDES1_BUFFER2_SIZE_MASK); ++ if (bfsize >= BUF_SIZE_2KiB) { ++ int bfsize2; ++ ++ bfsize2 = min(bfsize - BUF_SIZE_2KiB + 1, BUF_SIZE_2KiB - 1); ++ p->des1 |= cpu_to_le32((bfsize2 << RDES1_BUFFER2_SIZE_SHIFT) ++ & RDES1_BUFFER2_SIZE_MASK); ++ } + + if (end) + p->des1 |= cpu_to_le32(RDES1_END_RING); +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c +index 736e29635b77..313a58b68fee 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c +@@ -296,7 +296,7 @@ exit: + } + + static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic, +- int mode, int end) ++ int mode, int end, int bfsize) + { + dwmac4_set_rx_owner(p, disable_rx_ic); + } +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c +index 1d858fdec997..98fa471da7c0 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c +@@ -123,7 +123,7 @@ static int dwxgmac2_get_rx_timestamp_status(void *desc, void *next_desc, + } + + static void dwxgmac2_init_rx_desc(struct dma_desc *p, int disable_rx_ic, +- int mode, int end) ++ int mode, int end, int bfsize) + { + dwxgmac2_set_rx_owner(p, disable_rx_ic); + } +diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +index 5ef91a790f9d..5202d6ad7919 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +@@ -201,6 +201,11 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x, + if (unlikely(rdes0 & RDES0_OWN)) + return dma_own; + ++ if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) { ++ stats->rx_length_errors++; ++ return discard_frame; ++ } ++ + if (unlikely(rdes0 & RDES0_ERROR_SUMMARY)) { + if (unlikely(rdes0 & RDES0_DESCRIPTOR_ERROR)) { + x->rx_desc++; +@@ -231,9 +236,10 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x, + * It doesn't match with the information reported into the databook. + * At any rate, we need to understand if the CSUM hw computation is ok + * and report this info to the upper layers. */ +- ret = enh_desc_coe_rdes0(!!(rdes0 & RDES0_IPC_CSUM_ERROR), +- !!(rdes0 & RDES0_FRAME_TYPE), +- !!(rdes0 & ERDES0_RX_MAC_ADDR)); ++ if (likely(ret == good_frame)) ++ ret = enh_desc_coe_rdes0(!!(rdes0 & RDES0_IPC_CSUM_ERROR), ++ !!(rdes0 & RDES0_FRAME_TYPE), ++ !!(rdes0 & ERDES0_RX_MAC_ADDR)); + + if (unlikely(rdes0 & RDES0_DRIBBLING)) + x->dribbling_bit++; +@@ -259,15 +265,19 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x, + } + + static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, +- int mode, int end) ++ int mode, int end, int bfsize) + { ++ int bfsize1; ++ + p->des0 |= cpu_to_le32(RDES0_OWN); +- p->des1 |= cpu_to_le32(BUF_SIZE_8KiB & ERDES1_BUFFER1_SIZE_MASK); ++ ++ bfsize1 = min(bfsize, BUF_SIZE_8KiB); ++ p->des1 |= cpu_to_le32(bfsize1 & ERDES1_BUFFER1_SIZE_MASK); + + if (mode == STMMAC_CHAIN_MODE) + ehn_desc_rx_set_on_chain(p); + else +- ehn_desc_rx_set_on_ring(p, end); ++ ehn_desc_rx_set_on_ring(p, end, bfsize); + + if (disable_rx_ic) + p->des1 |= cpu_to_le32(ERDES1_DISABLE_IC); +diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h +index 92b8944f26e3..5bb00234d961 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h ++++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h +@@ -33,7 +33,7 @@ struct dma_extended_desc; + struct stmmac_desc_ops { + /* DMA RX descriptor ring initialization */ + void (*init_rx_desc)(struct dma_desc *p, int disable_rx_ic, int mode, +- int end); ++ int end, int bfsize); + /* DMA TX descriptor ring initialization */ + void (*init_tx_desc)(struct dma_desc *p, int mode, int end); + /* Invoked by the xmit function to prepare the tx descriptor */ +diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +index de65bb29feba..b7dd4e3c760d 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +@@ -91,8 +91,6 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x, + return dma_own; + + if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) { +- pr_warn("%s: Oversized frame spanned multiple buffers\n", +- __func__); + stats->rx_length_errors++; + return discard_frame; + } +@@ -135,15 +133,19 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x, + } + + static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode, +- int end) ++ int end, int bfsize) + { ++ int bfsize1; ++ + p->des0 |= cpu_to_le32(RDES0_OWN); +- p->des1 |= cpu_to_le32((BUF_SIZE_2KiB - 1) & RDES1_BUFFER1_SIZE_MASK); ++ ++ bfsize1 = min(bfsize, BUF_SIZE_2KiB - 1); ++ p->des1 |= cpu_to_le32(bfsize & RDES1_BUFFER1_SIZE_MASK); + + if (mode == STMMAC_CHAIN_MODE) + ndesc_rx_set_on_chain(p, end); + else +- ndesc_rx_set_on_ring(p, end); ++ ndesc_rx_set_on_ring(p, end, bfsize); + + if (disable_rx_ic) + p->des1 |= cpu_to_le32(RDES1_DISABLE_IC); +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 39c105092214..5debe93ea4eb 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1111,11 +1111,13 @@ static void stmmac_clear_rx_descriptors(struct stmmac_priv *priv, u32 queue) + if (priv->extend_desc) + stmmac_init_rx_desc(priv, &rx_q->dma_erx[i].basic, + priv->use_riwt, priv->mode, +- (i == DMA_RX_SIZE - 1)); ++ (i == DMA_RX_SIZE - 1), ++ priv->dma_buf_sz); + else + stmmac_init_rx_desc(priv, &rx_q->dma_rx[i], + priv->use_riwt, priv->mode, +- (i == DMA_RX_SIZE - 1)); ++ (i == DMA_RX_SIZE - 1), ++ priv->dma_buf_sz); + } + + /** +@@ -3331,9 +3333,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) + { + struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; + struct stmmac_channel *ch = &priv->channel[queue]; +- unsigned int entry = rx_q->cur_rx; ++ unsigned int next_entry = rx_q->cur_rx; + int coe = priv->hw->rx_csum; +- unsigned int next_entry; + unsigned int count = 0; + bool xmac; + +@@ -3351,10 +3352,12 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) + stmmac_display_ring(priv, rx_head, DMA_RX_SIZE, true); + } + while (count < limit) { +- int status; ++ int entry, status; + struct dma_desc *p; + struct dma_desc *np; + ++ entry = next_entry; ++ + if (priv->extend_desc) + p = (struct dma_desc *)(rx_q->dma_erx + entry); + else +@@ -3410,11 +3413,12 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) + * ignored + */ + if (frame_len > priv->dma_buf_sz) { +- netdev_err(priv->dev, +- "len %d larger than size (%d)\n", +- frame_len, priv->dma_buf_sz); ++ if (net_ratelimit()) ++ netdev_err(priv->dev, ++ "len %d larger than size (%d)\n", ++ frame_len, priv->dma_buf_sz); + priv->dev->stats.rx_length_errors++; +- break; ++ continue; + } + + /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 +@@ -3449,7 +3453,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) + dev_warn(priv->device, + "packet dropped\n"); + priv->dev->stats.rx_dropped++; +- break; ++ continue; + } + + dma_sync_single_for_cpu(priv->device, +@@ -3469,11 +3473,12 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) + } else { + skb = rx_q->rx_skbuff[entry]; + if (unlikely(!skb)) { +- netdev_err(priv->dev, +- "%s: Inconsistent Rx chain\n", +- priv->dev->name); ++ if (net_ratelimit()) ++ netdev_err(priv->dev, ++ "%s: Inconsistent Rx chain\n", ++ priv->dev->name); + priv->dev->stats.rx_dropped++; +- break; ++ continue; + } + prefetch(skb->data - NET_IP_ALIGN); + rx_q->rx_skbuff[entry] = NULL; +@@ -3508,7 +3513,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) + priv->dev->stats.rx_packets++; + priv->dev->stats.rx_bytes += frame_len; + } +- entry = next_entry; + } + + stmmac_rx_refill(priv, queue); +diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c +index 36151e61a26f..c04d934b23b4 100644 +--- a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c ++++ b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c +@@ -1,7 +1,7 @@ + /****************************************************************************** + * + * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. +- * Copyright(c) 2018 Intel Corporation ++ * Copyright(c) 2018 - 2019 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as +@@ -140,6 +140,7 @@ const struct iwl_cfg iwl5350_agn_cfg = { + .ht_params = &iwl5000_ht_params, + .led_mode = IWL_LED_BLINK, + .internal_wimax_coex = true, ++ .csr = &iwl_csr_v1, + }; + + #define IWL_DEVICE_5150 \ +diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c +index d49fbd58afa7..bfbe3aa058d9 100644 +--- a/drivers/net/wireless/marvell/mwifiex/sdio.c ++++ b/drivers/net/wireless/marvell/mwifiex/sdio.c +@@ -181,7 +181,7 @@ static int mwifiex_sdio_resume(struct device *dev) + + adapter = card->adapter; + +- if (test_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags)) { ++ if (!test_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags)) { + mwifiex_dbg(adapter, WARN, + "device already resumed\n"); + return 0; +diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c +index b5ec96abd048..776b7e9e23b9 100644 +--- a/drivers/nvme/target/core.c ++++ b/drivers/nvme/target/core.c +@@ -921,6 +921,15 @@ bool nvmet_host_allowed(struct nvmet_req *req, struct nvmet_subsys *subsys, + return __nvmet_host_allowed(subsys, hostnqn); + } + ++static void nvmet_fatal_error_handler(struct work_struct *work) ++{ ++ struct nvmet_ctrl *ctrl = ++ container_of(work, struct nvmet_ctrl, fatal_err_work); ++ ++ pr_err("ctrl %d fatal error occurred!\n", ctrl->cntlid); ++ ctrl->ops->delete_ctrl(ctrl); ++} ++ + u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn, + struct nvmet_req *req, u32 kato, struct nvmet_ctrl **ctrlp) + { +@@ -962,6 +971,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn, + + INIT_WORK(&ctrl->async_event_work, nvmet_async_event_work); + INIT_LIST_HEAD(&ctrl->async_events); ++ INIT_WORK(&ctrl->fatal_err_work, nvmet_fatal_error_handler); + + memcpy(ctrl->subsysnqn, subsysnqn, NVMF_NQN_SIZE); + memcpy(ctrl->hostnqn, hostnqn, NVMF_NQN_SIZE); +@@ -1076,21 +1086,11 @@ void nvmet_ctrl_put(struct nvmet_ctrl *ctrl) + kref_put(&ctrl->ref, nvmet_ctrl_free); + } + +-static void nvmet_fatal_error_handler(struct work_struct *work) +-{ +- struct nvmet_ctrl *ctrl = +- container_of(work, struct nvmet_ctrl, fatal_err_work); +- +- pr_err("ctrl %d fatal error occurred!\n", ctrl->cntlid); +- ctrl->ops->delete_ctrl(ctrl); +-} +- + void nvmet_ctrl_fatal_error(struct nvmet_ctrl *ctrl) + { + mutex_lock(&ctrl->lock); + if (!(ctrl->csts & NVME_CSTS_CFS)) { + ctrl->csts |= NVME_CSTS_CFS; +- INIT_WORK(&ctrl->fatal_err_work, nvmet_fatal_error_handler); + schedule_work(&ctrl->fatal_err_work); + } + mutex_unlock(&ctrl->lock); +diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c +index e0dcdb3cc070..088d1c2047e6 100644 +--- a/drivers/platform/x86/intel_pmc_core.c ++++ b/drivers/platform/x86/intel_pmc_core.c +@@ -185,7 +185,7 @@ static const struct pmc_bit_map cnp_pfear_map[] = { + {"CNVI", BIT(3)}, + {"UFS0", BIT(4)}, + {"EMMC", BIT(5)}, +- {"Res_6", BIT(6)}, ++ {"SPF", BIT(6)}, + {"SBR6", BIT(7)}, + + {"SBR7", BIT(0)}, +@@ -682,7 +682,7 @@ static int __init pmc_core_probe(void) + * Sunrisepoint PCH regmap can't be used. Use Cannonlake PCH regmap + * in this case. + */ +- if (!pci_dev_present(pmc_pci_ids)) ++ if (pmcdev->map == &spt_reg_map && !pci_dev_present(pmc_pci_ids)) + pmcdev->map = &cnp_reg_map; + + if (lpit_read_residency_count_address(&slp_s0_addr)) +diff --git a/drivers/platform/x86/pmc_atom.c b/drivers/platform/x86/pmc_atom.c +index 8f018b3f3cd4..eaec2d306481 100644 +--- a/drivers/platform/x86/pmc_atom.c ++++ b/drivers/platform/x86/pmc_atom.c +@@ -17,6 +17,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -391,11 +392,27 @@ static int pmc_dbgfs_register(struct pmc_dev *pmc) + } + #endif /* CONFIG_DEBUG_FS */ + ++/* ++ * Some systems need one or more of their pmc_plt_clks to be ++ * marked as critical. ++ */ ++static const struct dmi_system_id critclk_systems[] __initconst = { ++ { ++ .ident = "MPL CEC1x", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "MPL AG"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "CEC10 Family"), ++ }, ++ }, ++ { /*sentinel*/ } ++}; ++ + static int pmc_setup_clks(struct pci_dev *pdev, void __iomem *pmc_regmap, + const struct pmc_data *pmc_data) + { + struct platform_device *clkdev; + struct pmc_clk_data *clk_data; ++ const struct dmi_system_id *d = dmi_first_match(critclk_systems); + + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) +@@ -403,6 +420,10 @@ static int pmc_setup_clks(struct pci_dev *pdev, void __iomem *pmc_regmap, + + clk_data->base = pmc_regmap; /* offset is added by client */ + clk_data->clks = pmc_data->clks; ++ if (d) { ++ clk_data->critical = true; ++ pr_info("%s critclks quirk enabled\n", d->ident); ++ } + + clkdev = platform_device_register_data(&pdev->dev, "clk-pmc-atom", + PLATFORM_DEVID_NONE, +diff --git a/drivers/reset/reset-meson-audio-arb.c b/drivers/reset/reset-meson-audio-arb.c +index 91751617b37a..c53a2185a039 100644 +--- a/drivers/reset/reset-meson-audio-arb.c ++++ b/drivers/reset/reset-meson-audio-arb.c +@@ -130,6 +130,7 @@ static int meson_audio_arb_probe(struct platform_device *pdev) + arb->rstc.nr_resets = ARRAY_SIZE(axg_audio_arb_reset_bits); + arb->rstc.ops = &meson_audio_arb_rstc_ops; + arb->rstc.of_node = dev->of_node; ++ arb->rstc.owner = THIS_MODULE; + + /* + * Enable general : +diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c +index e5444296075e..4d6bf9304ceb 100644 +--- a/drivers/rtc/rtc-cros-ec.c ++++ b/drivers/rtc/rtc-cros-ec.c +@@ -298,7 +298,7 @@ static int cros_ec_rtc_suspend(struct device *dev) + struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(&pdev->dev); + + if (device_may_wakeup(dev)) +- enable_irq_wake(cros_ec_rtc->cros_ec->irq); ++ return enable_irq_wake(cros_ec_rtc->cros_ec->irq); + + return 0; + } +@@ -309,7 +309,7 @@ static int cros_ec_rtc_resume(struct device *dev) + struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(&pdev->dev); + + if (device_may_wakeup(dev)) +- disable_irq_wake(cros_ec_rtc->cros_ec->irq); ++ return disable_irq_wake(cros_ec_rtc->cros_ec->irq); + + return 0; + } +diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c +index b4e054c64bad..69b54e5556c0 100644 +--- a/drivers/rtc/rtc-da9063.c ++++ b/drivers/rtc/rtc-da9063.c +@@ -480,6 +480,13 @@ static int da9063_rtc_probe(struct platform_device *pdev) + da9063_data_to_tm(data, &rtc->alarm_time, rtc); + rtc->rtc_sync = false; + ++ /* ++ * TODO: some models have alarms on a minute boundary but still support ++ * real hardware interrupts. Add this once the core supports it. ++ */ ++ if (config->rtc_data_start != RTC_SEC) ++ rtc->rtc_dev->uie_unsupported = 1; ++ + irq_alarm = platform_get_irq_byname(pdev, "ALARM"); + ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL, + da9063_alarm_event, +diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c +index 51ba414798a8..3d7414e5ed35 100644 +--- a/drivers/rtc/rtc-sh.c ++++ b/drivers/rtc/rtc-sh.c +@@ -377,7 +377,7 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm) + static inline int sh_rtc_read_alarm_value(struct sh_rtc *rtc, int reg_off) + { + unsigned int byte; +- int value = 0xff; /* return 0xff for ignored values */ ++ int value = -1; /* return -1 for ignored values */ + + byte = readb(rtc->regbase + reg_off); + if (byte & AR_ENB) { +diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c +index c4cbfd07b916..a08ff3bd6310 100644 +--- a/drivers/scsi/scsi_devinfo.c ++++ b/drivers/scsi/scsi_devinfo.c +@@ -238,6 +238,7 @@ static struct { + {"NETAPP", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, + {"LSI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, + {"ENGENIO", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, ++ {"LENOVO", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, + {"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36}, + {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN}, + {"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */ +diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c +index 5a58cbf3a75d..c14006ac98f9 100644 +--- a/drivers/scsi/scsi_dh.c ++++ b/drivers/scsi/scsi_dh.c +@@ -75,6 +75,7 @@ static const struct scsi_dh_blist scsi_dh_blist[] = { + {"NETAPP", "INF-01-00", "rdac", }, + {"LSI", "INF-01-00", "rdac", }, + {"ENGENIO", "INF-01-00", "rdac", }, ++ {"LENOVO", "DE_Series", "rdac", }, + {NULL, NULL, NULL }, + }; + +diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c +index f03dc03a42c3..0c2ba075bc71 100644 +--- a/drivers/scsi/storvsc_drv.c ++++ b/drivers/scsi/storvsc_drv.c +@@ -664,13 +664,22 @@ static void handle_sc_creation(struct vmbus_channel *new_sc) + static void handle_multichannel_storage(struct hv_device *device, int max_chns) + { + struct storvsc_device *stor_device; +- int num_cpus = num_online_cpus(); + int num_sc; + struct storvsc_cmd_request *request; + struct vstor_packet *vstor_packet; + int ret, t; + +- num_sc = ((max_chns > num_cpus) ? num_cpus : max_chns); ++ /* ++ * If the number of CPUs is artificially restricted, such as ++ * with maxcpus=1 on the kernel boot line, Hyper-V could offer ++ * sub-channels >= the number of CPUs. These sub-channels ++ * should not be created. The primary channel is already created ++ * and assigned to one CPU, so check against # CPUs - 1. ++ */ ++ num_sc = min((int)(num_online_cpus() - 1), max_chns); ++ if (!num_sc) ++ return; ++ + stor_device = get_out_stor_device(device); + if (!stor_device) + return; +diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c +index 3f22d1088713..68866f552290 100644 +--- a/drivers/staging/iio/addac/adt7316.c ++++ b/drivers/staging/iio/addac/adt7316.c +@@ -47,6 +47,8 @@ + #define ADT7516_MSB_AIN3 0xA + #define ADT7516_MSB_AIN4 0xB + #define ADT7316_DA_DATA_BASE 0x10 ++#define ADT7316_DA_10_BIT_LSB_SHIFT 6 ++#define ADT7316_DA_12_BIT_LSB_SHIFT 4 + #define ADT7316_DA_MSB_DATA_REGS 4 + #define ADT7316_LSB_DAC_A 0x10 + #define ADT7316_MSB_DAC_A 0x11 +@@ -1086,7 +1088,7 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev, + ldac_config = chip->ldac_config & (~ADT7516_DAC_IN_VREF_MASK); + if (data & 0x1) + ldac_config |= ADT7516_DAC_AB_IN_VREF; +- else if (data & 0x2) ++ if (data & 0x2) + ldac_config |= ADT7516_DAC_CD_IN_VREF; + } else { + ret = kstrtou8(buf, 16, &data); +@@ -1408,7 +1410,7 @@ static IIO_DEVICE_ATTR(ex_analog_temp_offset, 0644, + static ssize_t adt7316_show_DAC(struct adt7316_chip_info *chip, + int channel, char *buf) + { +- u16 data; ++ u16 data = 0; + u8 msb, lsb, offset; + int ret; + +@@ -1433,7 +1435,11 @@ static ssize_t adt7316_show_DAC(struct adt7316_chip_info *chip, + if (ret) + return -EIO; + +- data = (msb << offset) + (lsb & ((1 << offset) - 1)); ++ if (chip->dac_bits == 12) ++ data = lsb >> ADT7316_DA_12_BIT_LSB_SHIFT; ++ else if (chip->dac_bits == 10) ++ data = lsb >> ADT7316_DA_10_BIT_LSB_SHIFT; ++ data |= msb << offset; + + return sprintf(buf, "%d\n", data); + } +@@ -1441,7 +1447,7 @@ static ssize_t adt7316_show_DAC(struct adt7316_chip_info *chip, + static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip, + int channel, const char *buf, size_t len) + { +- u8 msb, lsb, offset; ++ u8 msb, lsb, lsb_reg, offset; + u16 data; + int ret; + +@@ -1459,9 +1465,13 @@ static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip, + return -EINVAL; + + if (chip->dac_bits > 8) { +- lsb = data & (1 << offset); ++ lsb = data & ((1 << offset) - 1); ++ if (chip->dac_bits == 12) ++ lsb_reg = lsb << ADT7316_DA_12_BIT_LSB_SHIFT; ++ else ++ lsb_reg = lsb << ADT7316_DA_10_BIT_LSB_SHIFT; + ret = chip->bus.write(chip->bus.client, +- ADT7316_DA_DATA_BASE + channel * 2, lsb); ++ ADT7316_DA_DATA_BASE + channel * 2, lsb_reg); + if (ret) + return -EIO; + } +diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c +index ef47c226e1d2..3255b2bb0fd5 100644 +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -473,11 +473,6 @@ static int usb_unbind_interface(struct device *dev) + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + +- /* Undo any residual pm_autopm_get_interface_* calls */ +- for (r = atomic_read(&intf->pm_usage_cnt); r > 0; --r) +- usb_autopm_put_interface_no_suspend(intf); +- atomic_set(&intf->pm_usage_cnt, 0); +- + if (!error) + usb_autosuspend_device(udev); + +@@ -1636,7 +1631,6 @@ void usb_autopm_put_interface(struct usb_interface *intf) + int status; + + usb_mark_last_busy(udev); +- atomic_dec(&intf->pm_usage_cnt); + status = pm_runtime_put_sync(&intf->dev); + dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", + __func__, atomic_read(&intf->dev.power.usage_count), +@@ -1665,7 +1659,6 @@ void usb_autopm_put_interface_async(struct usb_interface *intf) + int status; + + usb_mark_last_busy(udev); +- atomic_dec(&intf->pm_usage_cnt); + status = pm_runtime_put(&intf->dev); + dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", + __func__, atomic_read(&intf->dev.power.usage_count), +@@ -1687,7 +1680,6 @@ void usb_autopm_put_interface_no_suspend(struct usb_interface *intf) + struct usb_device *udev = interface_to_usbdev(intf); + + usb_mark_last_busy(udev); +- atomic_dec(&intf->pm_usage_cnt); + pm_runtime_put_noidle(&intf->dev); + } + EXPORT_SYMBOL_GPL(usb_autopm_put_interface_no_suspend); +@@ -1718,8 +1710,6 @@ int usb_autopm_get_interface(struct usb_interface *intf) + status = pm_runtime_get_sync(&intf->dev); + if (status < 0) + pm_runtime_put_sync(&intf->dev); +- else +- atomic_inc(&intf->pm_usage_cnt); + dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", + __func__, atomic_read(&intf->dev.power.usage_count), + status); +@@ -1753,8 +1743,6 @@ int usb_autopm_get_interface_async(struct usb_interface *intf) + status = pm_runtime_get(&intf->dev); + if (status < 0 && status != -EINPROGRESS) + pm_runtime_put_noidle(&intf->dev); +- else +- atomic_inc(&intf->pm_usage_cnt); + dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", + __func__, atomic_read(&intf->dev.power.usage_count), + status); +@@ -1778,7 +1766,6 @@ void usb_autopm_get_interface_no_resume(struct usb_interface *intf) + struct usb_device *udev = interface_to_usbdev(intf); + + usb_mark_last_busy(udev); +- atomic_inc(&intf->pm_usage_cnt); + pm_runtime_get_noresume(&intf->dev); + } + EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume); +diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c +index 4f33eb632a88..4020ce8db6ce 100644 +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -820,9 +820,11 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) + + if (dev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; +- if (size <= 0 || !buf || !index) ++ if (size <= 0 || !buf) + return -EINVAL; + buf[0] = 0; ++ if (index <= 0 || index >= 256) ++ return -EINVAL; + tbuf = kmalloc(256, GFP_NOIO); + if (!tbuf) + return -ENOMEM; +diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c +index baf72f95f0f1..213b52508621 100644 +--- a/drivers/usb/gadget/udc/dummy_hcd.c ++++ b/drivers/usb/gadget/udc/dummy_hcd.c +@@ -979,8 +979,18 @@ static int dummy_udc_start(struct usb_gadget *g, + struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g); + struct dummy *dum = dum_hcd->dum; + +- if (driver->max_speed == USB_SPEED_UNKNOWN) ++ switch (g->speed) { ++ /* All the speeds we support */ ++ case USB_SPEED_LOW: ++ case USB_SPEED_FULL: ++ case USB_SPEED_HIGH: ++ case USB_SPEED_SUPER: ++ break; ++ default: ++ dev_err(dummy_dev(dum_hcd), "Unsupported driver max speed %d\n", ++ driver->max_speed); + return -EINVAL; ++ } + + /* + * SLAVE side init ... the layer above hardware, which +@@ -1784,9 +1794,10 @@ static void dummy_timer(struct timer_list *t) + /* Bus speed is 500000 bytes/ms, so use a little less */ + total = 490000; + break; +- default: ++ default: /* Can't happen */ + dev_err(dummy_dev(dum_hcd), "bogus device speed\n"); +- return; ++ total = 0; ++ break; + } + + /* FIXME if HZ != 1000 this will probably misbehave ... */ +@@ -1828,7 +1839,7 @@ restart: + + /* Used up this frame's bandwidth? */ + if (total <= 0) +- break; ++ continue; + + /* find the gadget's ep for this request (if configured) */ + address = usb_pipeendpoint (urb->pipe); +diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c +index 6d9fd5f64903..7b306aa22d25 100644 +--- a/drivers/usb/misc/yurex.c ++++ b/drivers/usb/misc/yurex.c +@@ -314,6 +314,7 @@ static void yurex_disconnect(struct usb_interface *interface) + usb_deregister_dev(interface, &yurex_class); + + /* prevent more I/O from starting */ ++ usb_poison_urb(dev->urb); + mutex_lock(&dev->io_mutex); + dev->interface = NULL; + mutex_unlock(&dev->io_mutex); +diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c +index 31b024441938..cc794e25a0b6 100644 +--- a/drivers/usb/storage/realtek_cr.c ++++ b/drivers/usb/storage/realtek_cr.c +@@ -763,18 +763,16 @@ static void rts51x_suspend_timer_fn(struct timer_list *t) + break; + case RTS51X_STAT_IDLE: + case RTS51X_STAT_SS: +- usb_stor_dbg(us, "RTS51X_STAT_SS, intf->pm_usage_cnt:%d, power.usage:%d\n", +- atomic_read(&us->pusb_intf->pm_usage_cnt), ++ usb_stor_dbg(us, "RTS51X_STAT_SS, power.usage:%d\n", + atomic_read(&us->pusb_intf->dev.power.usage_count)); + +- if (atomic_read(&us->pusb_intf->pm_usage_cnt) > 0) { ++ if (atomic_read(&us->pusb_intf->dev.power.usage_count) > 0) { + usb_stor_dbg(us, "Ready to enter SS state\n"); + rts51x_set_stat(chip, RTS51X_STAT_SS); + /* ignore mass storage interface's children */ + pm_suspend_ignore_children(&us->pusb_intf->dev, true); + usb_autopm_put_interface_async(us->pusb_intf); +- usb_stor_dbg(us, "RTS51X_STAT_SS 01, intf->pm_usage_cnt:%d, power.usage:%d\n", +- atomic_read(&us->pusb_intf->pm_usage_cnt), ++ usb_stor_dbg(us, "RTS51X_STAT_SS 01, power.usage:%d\n", + atomic_read(&us->pusb_intf->dev.power.usage_count)); + } + break; +@@ -807,11 +805,10 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) + int ret; + + if (working_scsi(srb)) { +- usb_stor_dbg(us, "working scsi, intf->pm_usage_cnt:%d, power.usage:%d\n", +- atomic_read(&us->pusb_intf->pm_usage_cnt), ++ usb_stor_dbg(us, "working scsi, power.usage:%d\n", + atomic_read(&us->pusb_intf->dev.power.usage_count)); + +- if (atomic_read(&us->pusb_intf->pm_usage_cnt) <= 0) { ++ if (atomic_read(&us->pusb_intf->dev.power.usage_count) <= 0) { + ret = usb_autopm_get_interface(us->pusb_intf); + usb_stor_dbg(us, "working scsi, ret=%d\n", ret); + } +diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c +index 97b09a42a10c..dbfb2f24d71e 100644 +--- a/drivers/usb/usbip/stub_rx.c ++++ b/drivers/usb/usbip/stub_rx.c +@@ -361,16 +361,10 @@ static int get_pipe(struct stub_device *sdev, struct usbip_header *pdu) + } + + if (usb_endpoint_xfer_isoc(epd)) { +- /* validate packet size and number of packets */ +- unsigned int maxp, packets, bytes; +- +- maxp = usb_endpoint_maxp(epd); +- maxp *= usb_endpoint_maxp_mult(epd); +- bytes = pdu->u.cmd_submit.transfer_buffer_length; +- packets = DIV_ROUND_UP(bytes, maxp); +- ++ /* validate number of packets */ + if (pdu->u.cmd_submit.number_of_packets < 0 || +- pdu->u.cmd_submit.number_of_packets > packets) { ++ pdu->u.cmd_submit.number_of_packets > ++ USBIP_MAX_ISO_PACKETS) { + dev_err(&sdev->udev->dev, + "CMD_SUBMIT: isoc invalid num packets %d\n", + pdu->u.cmd_submit.number_of_packets); +diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h +index bf8afe9b5883..8be857a4fa13 100644 +--- a/drivers/usb/usbip/usbip_common.h ++++ b/drivers/usb/usbip/usbip_common.h +@@ -121,6 +121,13 @@ extern struct device_attribute dev_attr_usbip_debug; + #define USBIP_DIR_OUT 0x00 + #define USBIP_DIR_IN 0x01 + ++/* ++ * Arbitrary limit for the maximum number of isochronous packets in an URB, ++ * compare for example the uhci_submit_isochronous function in ++ * drivers/usb/host/uhci-q.c ++ */ ++#define USBIP_MAX_ISO_PACKETS 1024 ++ + /** + * struct usbip_header_basic - data pertinent to every request + * @command: the usbip request type +diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c +index cddb453a1ba5..6cf00d9f512b 100644 +--- a/drivers/vfio/pci/vfio_pci.c ++++ b/drivers/vfio/pci/vfio_pci.c +@@ -1443,11 +1443,11 @@ static void __init vfio_pci_fill_ids(void) + rc = pci_add_dynid(&vfio_pci_driver, vendor, device, + subvendor, subdevice, class, class_mask, 0); + if (rc) +- pr_warn("failed to add dynamic id [%04hx:%04hx[%04hx:%04hx]] class %#08x/%08x (%d)\n", ++ pr_warn("failed to add dynamic id [%04x:%04x[%04x:%04x]] class %#08x/%08x (%d)\n", + vendor, device, subvendor, subdevice, + class, class_mask, rc); + else +- pr_info("add [%04hx:%04hx[%04hx:%04hx]] class %#08x/%08x\n", ++ pr_info("add [%04x:%04x[%04x:%04x]] class %#08x/%08x\n", + vendor, device, subvendor, subdevice, + class, class_mask); + } +diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c +index 0f4ecfcdb549..a9fb77585272 100644 +--- a/drivers/w1/masters/ds2490.c ++++ b/drivers/w1/masters/ds2490.c +@@ -1016,15 +1016,15 @@ static int ds_probe(struct usb_interface *intf, + /* alternative 3, 1ms interrupt (greatly speeds search), 64 byte bulk */ + alt = 3; + err = usb_set_interface(dev->udev, +- intf->altsetting[alt].desc.bInterfaceNumber, alt); ++ intf->cur_altsetting->desc.bInterfaceNumber, alt); + if (err) { + dev_err(&dev->udev->dev, "Failed to set alternative setting %d " + "for %d interface: err=%d.\n", alt, +- intf->altsetting[alt].desc.bInterfaceNumber, err); ++ intf->cur_altsetting->desc.bInterfaceNumber, err); + goto err_out_clear; + } + +- iface_desc = &intf->altsetting[alt]; ++ iface_desc = intf->cur_altsetting; + if (iface_desc->desc.bNumEndpoints != NUM_EP-1) { + pr_info("Num endpoints=%d. It is not DS9490R.\n", + iface_desc->desc.bNumEndpoints); +diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c +index c3e201025ef0..0782ff3c2273 100644 +--- a/drivers/xen/xenbus/xenbus_dev_frontend.c ++++ b/drivers/xen/xenbus/xenbus_dev_frontend.c +@@ -622,9 +622,7 @@ static int xenbus_file_open(struct inode *inode, struct file *filp) + if (xen_store_evtchn == 0) + return -ENOENT; + +- nonseekable_open(inode, filp); +- +- filp->f_mode &= ~FMODE_ATOMIC_POS; /* cdev-style semantics */ ++ stream_open(inode, filp); + + u = kzalloc(sizeof(*u), GFP_KERNEL); + if (u == NULL) +diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c +index 41ef452c1fcf..e5126fad57c5 100644 +--- a/fs/debugfs/inode.c ++++ b/fs/debugfs/inode.c +@@ -163,19 +163,24 @@ static int debugfs_show_options(struct seq_file *m, struct dentry *root) + return 0; + } + +-static void debugfs_evict_inode(struct inode *inode) ++static void debugfs_i_callback(struct rcu_head *head) + { +- truncate_inode_pages_final(&inode->i_data); +- clear_inode(inode); ++ struct inode *inode = container_of(head, struct inode, i_rcu); + if (S_ISLNK(inode->i_mode)) + kfree(inode->i_link); ++ free_inode_nonrcu(inode); ++} ++ ++static void debugfs_destroy_inode(struct inode *inode) ++{ ++ call_rcu(&inode->i_rcu, debugfs_i_callback); + } + + static const struct super_operations debugfs_super_operations = { + .statfs = simple_statfs, + .remount_fs = debugfs_remount, + .show_options = debugfs_show_options, +- .evict_inode = debugfs_evict_inode, ++ .destroy_inode = debugfs_destroy_inode, + }; + + static void debugfs_release_dentry(struct dentry *dentry) +diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c +index a7fa037b876b..a3a3d256fb0e 100644 +--- a/fs/hugetlbfs/inode.c ++++ b/fs/hugetlbfs/inode.c +@@ -741,11 +741,17 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, + umode_t mode, dev_t dev) + { + struct inode *inode; +- struct resv_map *resv_map; ++ struct resv_map *resv_map = NULL; + +- resv_map = resv_map_alloc(); +- if (!resv_map) +- return NULL; ++ /* ++ * Reserve maps are only needed for inodes that can have associated ++ * page allocations. ++ */ ++ if (S_ISREG(mode) || S_ISLNK(mode)) { ++ resv_map = resv_map_alloc(); ++ if (!resv_map) ++ return NULL; ++ } + + inode = new_inode(sb); + if (inode) { +@@ -780,8 +786,10 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, + break; + } + lockdep_annotate_inode_mutex_key(inode); +- } else +- kref_put(&resv_map->refs, resv_map_release); ++ } else { ++ if (resv_map) ++ kref_put(&resv_map->refs, resv_map_release); ++ } + + return inode; + } +diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c +index 389ea53ea487..bccfc40b3a74 100644 +--- a/fs/jffs2/readinode.c ++++ b/fs/jffs2/readinode.c +@@ -1414,11 +1414,6 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) + + jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); + +- if (f->target) { +- kfree(f->target); +- f->target = NULL; +- } +- + fds = f->dents; + while(fds) { + fd = fds; +diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c +index bb6ae387469f..05d892c79339 100644 +--- a/fs/jffs2/super.c ++++ b/fs/jffs2/super.c +@@ -47,7 +47,10 @@ static struct inode *jffs2_alloc_inode(struct super_block *sb) + static void jffs2_i_callback(struct rcu_head *head) + { + struct inode *inode = container_of(head, struct inode, i_rcu); +- kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode)); ++ struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); ++ ++ kfree(f->target); ++ kmem_cache_free(jffs2_inode_cachep, f); + } + + static void jffs2_destroy_inode(struct inode *inode) +diff --git a/fs/open.c b/fs/open.c +index f1c2f855fd43..a00350018a47 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -1215,3 +1215,21 @@ int nonseekable_open(struct inode *inode, struct file *filp) + } + + EXPORT_SYMBOL(nonseekable_open); ++ ++/* ++ * stream_open is used by subsystems that want stream-like file descriptors. ++ * Such file descriptors are not seekable and don't have notion of position ++ * (file.f_pos is always 0). Contrary to file descriptors of other regular ++ * files, .read() and .write() can run simultaneously. ++ * ++ * stream_open never fails and is marked to return int so that it could be ++ * directly used as file_operations.open . ++ */ ++int stream_open(struct inode *inode, struct file *filp) ++{ ++ filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE | FMODE_ATOMIC_POS); ++ filp->f_mode |= FMODE_STREAM; ++ return 0; ++} ++ ++EXPORT_SYMBOL(stream_open); +diff --git a/fs/read_write.c b/fs/read_write.c +index 562974a0616c..85fd7a8ee29e 100644 +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -560,12 +560,13 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ + + static inline loff_t file_pos_read(struct file *file) + { +- return file->f_pos; ++ return file->f_mode & FMODE_STREAM ? 0 : file->f_pos; + } + + static inline void file_pos_write(struct file *file, loff_t pos) + { +- file->f_pos = pos; ++ if ((file->f_mode & FMODE_STREAM) == 0) ++ file->f_pos = pos; + } + + ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count) +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 111c94c4baa1..d4e1b43a53c3 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -153,6 +153,9 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, + #define FMODE_OPENED ((__force fmode_t)0x80000) + #define FMODE_CREATED ((__force fmode_t)0x100000) + ++/* File is stream-like */ ++#define FMODE_STREAM ((__force fmode_t)0x200000) ++ + /* File was opened by fanotify and shouldn't generate fanotify events */ + #define FMODE_NONOTIFY ((__force fmode_t)0x4000000) + +@@ -3019,6 +3022,7 @@ extern loff_t no_seek_end_llseek_size(struct file *, loff_t, int, loff_t); + extern loff_t no_seek_end_llseek(struct file *, loff_t, int); + extern int generic_file_open(struct inode * inode, struct file * filp); + extern int nonseekable_open(struct inode * inode, struct file * filp); ++extern int stream_open(struct inode * inode, struct file * filp); + + #ifdef CONFIG_BLOCK + typedef void (dio_submit_t)(struct bio *bio, struct inode *inode, +diff --git a/include/linux/i2c.h b/include/linux/i2c.h +index 65b4eaed1d96..7e748648c7d3 100644 +--- a/include/linux/i2c.h ++++ b/include/linux/i2c.h +@@ -333,6 +333,7 @@ struct i2c_client { + char name[I2C_NAME_SIZE]; + struct i2c_adapter *adapter; /* the adapter we sit on */ + struct device dev; /* the device structure */ ++ int init_irq; /* irq set at initialization */ + int irq; /* irq issued by device */ + struct list_head detected; + #if IS_ENABLED(CONFIG_I2C_SLAVE) +diff --git a/include/linux/platform_data/x86/clk-pmc-atom.h b/include/linux/platform_data/x86/clk-pmc-atom.h +index 3ab892208343..7a37ac27d0fb 100644 +--- a/include/linux/platform_data/x86/clk-pmc-atom.h ++++ b/include/linux/platform_data/x86/clk-pmc-atom.h +@@ -35,10 +35,13 @@ struct pmc_clk { + * + * @base: PMC clock register base offset + * @clks: pointer to set of registered clocks, typically 0..5 ++ * @critical: flag to indicate if firmware enabled pmc_plt_clks ++ * should be marked as critial or not + */ + struct pmc_clk_data { + void __iomem *base; + const struct pmc_clk *clks; ++ bool critical; + }; + + #endif /* __PLATFORM_DATA_X86_CLK_PMC_ATOM_H */ +diff --git a/include/linux/usb.h b/include/linux/usb.h +index 5e49e82c4368..ff010d1fd1c7 100644 +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -200,7 +200,6 @@ usb_find_last_int_out_endpoint(struct usb_host_interface *alt, + * @dev: driver model's view of this device + * @usb_dev: if an interface is bound to the USB major, this will point + * to the sysfs representation for that device. +- * @pm_usage_cnt: PM usage counter for this interface + * @reset_ws: Used for scheduling resets from atomic context. + * @resetting_device: USB core reset the device, so use alt setting 0 as + * current; needs bandwidth alloc after reset. +@@ -257,7 +256,6 @@ struct usb_interface { + + struct device dev; /* interface specific device info */ + struct device *usb_dev; +- atomic_t pm_usage_cnt; /* usage counter for autosuspend */ + struct work_struct reset_ws; /* for resets in atomic context */ + }; + #define to_usb_interface(d) container_of(d, struct usb_interface, dev) +diff --git a/mm/kmemleak.c b/mm/kmemleak.c +index 17dd883198ae..72e3fb3bb037 100644 +--- a/mm/kmemleak.c ++++ b/mm/kmemleak.c +@@ -1373,6 +1373,7 @@ static void scan_block(void *_start, void *_end, + /* + * Scan a large memory block in MAX_SCAN_SIZE chunks to reduce the latency. + */ ++#ifdef CONFIG_SMP + static void scan_large_block(void *start, void *end) + { + void *next; +@@ -1384,6 +1385,7 @@ static void scan_large_block(void *start, void *end) + cond_resched(); + } + } ++#endif + + /* + * Scan a memory block corresponding to a kmemleak_object. A condition is +@@ -1501,11 +1503,6 @@ static void kmemleak_scan(void) + } + rcu_read_unlock(); + +- /* data/bss scanning */ +- scan_large_block(_sdata, _edata); +- scan_large_block(__bss_start, __bss_stop); +- scan_large_block(__start_ro_after_init, __end_ro_after_init); +- + #ifdef CONFIG_SMP + /* per-cpu sections scanning */ + for_each_possible_cpu(i) +@@ -2036,6 +2033,17 @@ void __init kmemleak_init(void) + } + local_irq_restore(flags); + ++ /* register the data/bss sections */ ++ create_object((unsigned long)_sdata, _edata - _sdata, ++ KMEMLEAK_GREY, GFP_ATOMIC); ++ create_object((unsigned long)__bss_start, __bss_stop - __bss_start, ++ KMEMLEAK_GREY, GFP_ATOMIC); ++ /* only register .data..ro_after_init if not within .data */ ++ if (__start_ro_after_init < _sdata || __end_ro_after_init > _edata) ++ create_object((unsigned long)__start_ro_after_init, ++ __end_ro_after_init - __start_ro_after_init, ++ KMEMLEAK_GREY, GFP_ATOMIC); ++ + /* + * This is the point where tracking allocations is safe. Automatic + * scanning is started during the late initcall. Add the early logged +diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c +index ef0dec20c7d8..5da183b2f4c9 100644 +--- a/net/batman-adv/bat_v_elp.c ++++ b/net/batman-adv/bat_v_elp.c +@@ -104,8 +104,10 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh) + + ret = cfg80211_get_station(real_netdev, neigh->addr, &sinfo); + +- /* free the TID stats immediately */ +- cfg80211_sinfo_release_content(&sinfo); ++ if (!ret) { ++ /* free the TID stats immediately */ ++ cfg80211_sinfo_release_content(&sinfo); ++ } + + dev_put(real_netdev); + if (ret == -ENOENT) { +diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c +index 5f1aeeded0e3..85faf25c2912 100644 +--- a/net/batman-adv/bridge_loop_avoidance.c ++++ b/net/batman-adv/bridge_loop_avoidance.c +@@ -803,6 +803,8 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, + const u8 *mac, const unsigned short vid) + { + struct batadv_bla_claim search_claim, *claim; ++ struct batadv_bla_claim *claim_removed_entry; ++ struct hlist_node *claim_removed_node; + + ether_addr_copy(search_claim.addr, mac); + search_claim.vid = vid; +@@ -813,10 +815,18 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, + batadv_dbg(BATADV_DBG_BLA, bat_priv, "%s(): %pM, vid %d\n", __func__, + mac, batadv_print_vid(vid)); + +- batadv_hash_remove(bat_priv->bla.claim_hash, batadv_compare_claim, +- batadv_choose_claim, claim); +- batadv_claim_put(claim); /* reference from the hash is gone */ ++ claim_removed_node = batadv_hash_remove(bat_priv->bla.claim_hash, ++ batadv_compare_claim, ++ batadv_choose_claim, claim); ++ if (!claim_removed_node) ++ goto free_claim; + ++ /* reference from the hash is gone */ ++ claim_removed_entry = hlist_entry(claim_removed_node, ++ struct batadv_bla_claim, hash_entry); ++ batadv_claim_put(claim_removed_entry); ++ ++free_claim: + /* don't need the reference from hash_find() anymore */ + batadv_claim_put(claim); + } +diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c +index d21624c44665..359ec1a6e822 100644 +--- a/net/batman-adv/translation-table.c ++++ b/net/batman-adv/translation-table.c +@@ -616,14 +616,26 @@ static void batadv_tt_global_free(struct batadv_priv *bat_priv, + struct batadv_tt_global_entry *tt_global, + const char *message) + { ++ struct batadv_tt_global_entry *tt_removed_entry; ++ struct hlist_node *tt_removed_node; ++ + batadv_dbg(BATADV_DBG_TT, bat_priv, + "Deleting global tt entry %pM (vid: %d): %s\n", + tt_global->common.addr, + batadv_print_vid(tt_global->common.vid), message); + +- batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, +- batadv_choose_tt, &tt_global->common); +- batadv_tt_global_entry_put(tt_global); ++ tt_removed_node = batadv_hash_remove(bat_priv->tt.global_hash, ++ batadv_compare_tt, ++ batadv_choose_tt, ++ &tt_global->common); ++ if (!tt_removed_node) ++ return; ++ ++ /* drop reference of remove hash entry */ ++ tt_removed_entry = hlist_entry(tt_removed_node, ++ struct batadv_tt_global_entry, ++ common.hash_entry); ++ batadv_tt_global_entry_put(tt_removed_entry); + } + + /** +@@ -1332,9 +1344,10 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr, + unsigned short vid, const char *message, + bool roaming) + { ++ struct batadv_tt_local_entry *tt_removed_entry; + struct batadv_tt_local_entry *tt_local_entry; + u16 flags, curr_flags = BATADV_NO_FLAGS; +- void *tt_entry_exists; ++ struct hlist_node *tt_removed_node; + + tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid); + if (!tt_local_entry) +@@ -1363,15 +1376,18 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr, + */ + batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL); + +- tt_entry_exists = batadv_hash_remove(bat_priv->tt.local_hash, ++ tt_removed_node = batadv_hash_remove(bat_priv->tt.local_hash, + batadv_compare_tt, + batadv_choose_tt, + &tt_local_entry->common); +- if (!tt_entry_exists) ++ if (!tt_removed_node) + goto out; + +- /* extra call to free the local tt entry */ +- batadv_tt_local_entry_put(tt_local_entry); ++ /* drop reference of remove hash entry */ ++ tt_removed_entry = hlist_entry(tt_removed_node, ++ struct batadv_tt_local_entry, ++ common.hash_entry); ++ batadv_tt_local_entry_put(tt_removed_entry); + + out: + if (tt_local_entry) +diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c +index c813207bb123..d37d4acafebf 100644 +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -838,7 +838,7 @@ void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) + + dir = sdata->vif.debugfs_dir; + +- if (!dir) ++ if (IS_ERR_OR_NULL(dir)) + return; + + sprintf(buf, "netdev:%s", sdata->name); +diff --git a/net/mac80211/key.c b/net/mac80211/key.c +index c054ac85793c..f20bb39f492d 100644 +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -167,8 +167,10 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) + * The driver doesn't know anything about VLAN interfaces. + * Hence, don't send GTKs for VLAN interfaces to the driver. + */ +- if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) ++ if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) { ++ ret = 1; + goto out_unsupported; ++ } + } + + ret = drv_set_key(key->local, SET_KEY, sdata, +@@ -213,11 +215,8 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) + /* all of these we can do in software - if driver can */ + if (ret == 1) + return 0; +- if (ieee80211_hw_check(&key->local->hw, SW_CRYPTO_CONTROL)) { +- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +- return 0; ++ if (ieee80211_hw_check(&key->local->hw, SW_CRYPTO_CONTROL)) + return -EINVAL; +- } + return 0; + default: + return -EINVAL; +diff --git a/scripts/coccinelle/api/stream_open.cocci b/scripts/coccinelle/api/stream_open.cocci +new file mode 100644 +index 000000000000..350145da7669 +--- /dev/null ++++ b/scripts/coccinelle/api/stream_open.cocci +@@ -0,0 +1,363 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Author: Kirill Smelkov (kirr@nexedi.com) ++// ++// Search for stream-like files that are using nonseekable_open and convert ++// them to stream_open. A stream-like file is a file that does not use ppos in ++// its read and write. Rationale for the conversion is to avoid deadlock in ++// between read and write. ++ ++virtual report ++virtual patch ++virtual explain // explain decisions in the patch (SPFLAGS="-D explain") ++ ++// stream-like reader & writer - ones that do not depend on f_pos. ++@ stream_reader @ ++identifier readstream, ppos; ++identifier f, buf, len; ++type loff_t; ++@@ ++ ssize_t readstream(struct file *f, char *buf, size_t len, loff_t *ppos) ++ { ++ ... when != ppos ++ } ++ ++@ stream_writer @ ++identifier writestream, ppos; ++identifier f, buf, len; ++type loff_t; ++@@ ++ ssize_t writestream(struct file *f, const char *buf, size_t len, loff_t *ppos) ++ { ++ ... when != ppos ++ } ++ ++ ++// a function that blocks ++@ blocks @ ++identifier block_f; ++identifier wait_event =~ "^wait_event_.*"; ++@@ ++ block_f(...) { ++ ... when exists ++ wait_event(...) ++ ... when exists ++ } ++ ++// stream_reader that can block inside. ++// ++// XXX wait_* can be called not directly from current function (e.g. func -> f -> g -> wait()) ++// XXX currently reader_blocks supports only direct and 1-level indirect cases. ++@ reader_blocks_direct @ ++identifier stream_reader.readstream; ++identifier wait_event =~ "^wait_event_.*"; ++@@ ++ readstream(...) ++ { ++ ... when exists ++ wait_event(...) ++ ... when exists ++ } ++ ++@ reader_blocks_1 @ ++identifier stream_reader.readstream; ++identifier blocks.block_f; ++@@ ++ readstream(...) ++ { ++ ... when exists ++ block_f(...) ++ ... when exists ++ } ++ ++@ reader_blocks depends on reader_blocks_direct || reader_blocks_1 @ ++identifier stream_reader.readstream; ++@@ ++ readstream(...) { ++ ... ++ } ++ ++ ++// file_operations + whether they have _any_ .read, .write, .llseek ... at all. ++// ++// XXX add support for file_operations xxx[N] = ... (sound/core/pcm_native.c) ++@ fops0 @ ++identifier fops; ++@@ ++ struct file_operations fops = { ++ ... ++ }; ++ ++@ has_read @ ++identifier fops0.fops; ++identifier read_f; ++@@ ++ struct file_operations fops = { ++ .read = read_f, ++ }; ++ ++@ has_read_iter @ ++identifier fops0.fops; ++identifier read_iter_f; ++@@ ++ struct file_operations fops = { ++ .read_iter = read_iter_f, ++ }; ++ ++@ has_write @ ++identifier fops0.fops; ++identifier write_f; ++@@ ++ struct file_operations fops = { ++ .write = write_f, ++ }; ++ ++@ has_write_iter @ ++identifier fops0.fops; ++identifier write_iter_f; ++@@ ++ struct file_operations fops = { ++ .write_iter = write_iter_f, ++ }; ++ ++@ has_llseek @ ++identifier fops0.fops; ++identifier llseek_f; ++@@ ++ struct file_operations fops = { ++ .llseek = llseek_f, ++ }; ++ ++@ has_no_llseek @ ++identifier fops0.fops; ++@@ ++ struct file_operations fops = { ++ .llseek = no_llseek, ++ }; ++ ++@ has_mmap @ ++identifier fops0.fops; ++identifier mmap_f; ++@@ ++ struct file_operations fops = { ++ .mmap = mmap_f, ++ }; ++ ++@ has_copy_file_range @ ++identifier fops0.fops; ++identifier copy_file_range_f; ++@@ ++ struct file_operations fops = { ++ .copy_file_range = copy_file_range_f, ++ }; ++ ++@ has_remap_file_range @ ++identifier fops0.fops; ++identifier remap_file_range_f; ++@@ ++ struct file_operations fops = { ++ .remap_file_range = remap_file_range_f, ++ }; ++ ++@ has_splice_read @ ++identifier fops0.fops; ++identifier splice_read_f; ++@@ ++ struct file_operations fops = { ++ .splice_read = splice_read_f, ++ }; ++ ++@ has_splice_write @ ++identifier fops0.fops; ++identifier splice_write_f; ++@@ ++ struct file_operations fops = { ++ .splice_write = splice_write_f, ++ }; ++ ++ ++// file_operations that is candidate for stream_open conversion - it does not ++// use mmap and other methods that assume @offset access to file. ++// ++// XXX for simplicity require no .{read/write}_iter and no .splice_{read/write} for now. ++// XXX maybe_steam.fops cannot be used in other rules - it gives "bad rule maybe_stream or bad variable fops". ++@ maybe_stream depends on (!has_llseek || has_no_llseek) && !has_mmap && !has_copy_file_range && !has_remap_file_range && !has_read_iter && !has_write_iter && !has_splice_read && !has_splice_write @ ++identifier fops0.fops; ++@@ ++ struct file_operations fops = { ++ }; ++ ++ ++// ---- conversions ---- ++ ++// XXX .open = nonseekable_open -> .open = stream_open ++// XXX .open = func -> openfunc -> nonseekable_open ++ ++// read & write ++// ++// if both are used in the same file_operations together with an opener - ++// under that conditions we can use stream_open instead of nonseekable_open. ++@ fops_rw depends on maybe_stream @ ++identifier fops0.fops, openfunc; ++identifier stream_reader.readstream; ++identifier stream_writer.writestream; ++@@ ++ struct file_operations fops = { ++ .open = openfunc, ++ .read = readstream, ++ .write = writestream, ++ }; ++ ++@ report_rw depends on report @ ++identifier fops_rw.openfunc; ++position p1; ++@@ ++ openfunc(...) { ++ <... ++ nonseekable_open@p1 ++ ...> ++ } ++ ++@ script:python depends on report && reader_blocks @ ++fops << fops0.fops; ++p << report_rw.p1; ++@@ ++coccilib.report.print_report(p[0], ++ "ERROR: %s: .read() can deadlock .write(); change nonseekable_open -> stream_open to fix." % (fops,)) ++ ++@ script:python depends on report && !reader_blocks @ ++fops << fops0.fops; ++p << report_rw.p1; ++@@ ++coccilib.report.print_report(p[0], ++ "WARNING: %s: .read() and .write() have stream semantic; safe to change nonseekable_open -> stream_open." % (fops,)) ++ ++ ++@ explain_rw_deadlocked depends on explain && reader_blocks @ ++identifier fops_rw.openfunc; ++@@ ++ openfunc(...) { ++ <... ++- nonseekable_open +++ nonseekable_open /* read & write (was deadlock) */ ++ ...> ++ } ++ ++ ++@ explain_rw_nodeadlock depends on explain && !reader_blocks @ ++identifier fops_rw.openfunc; ++@@ ++ openfunc(...) { ++ <... ++- nonseekable_open +++ nonseekable_open /* read & write (no direct deadlock) */ ++ ...> ++ } ++ ++@ patch_rw depends on patch @ ++identifier fops_rw.openfunc; ++@@ ++ openfunc(...) { ++ <... ++- nonseekable_open +++ stream_open ++ ...> ++ } ++ ++ ++// read, but not write ++@ fops_r depends on maybe_stream && !has_write @ ++identifier fops0.fops, openfunc; ++identifier stream_reader.readstream; ++@@ ++ struct file_operations fops = { ++ .open = openfunc, ++ .read = readstream, ++ }; ++ ++@ report_r depends on report @ ++identifier fops_r.openfunc; ++position p1; ++@@ ++ openfunc(...) { ++ <... ++ nonseekable_open@p1 ++ ...> ++ } ++ ++@ script:python depends on report @ ++fops << fops0.fops; ++p << report_r.p1; ++@@ ++coccilib.report.print_report(p[0], ++ "WARNING: %s: .read() has stream semantic; safe to change nonseekable_open -> stream_open." % (fops,)) ++ ++@ explain_r depends on explain @ ++identifier fops_r.openfunc; ++@@ ++ openfunc(...) { ++ <... ++- nonseekable_open +++ nonseekable_open /* read only */ ++ ...> ++ } ++ ++@ patch_r depends on patch @ ++identifier fops_r.openfunc; ++@@ ++ openfunc(...) { ++ <... ++- nonseekable_open +++ stream_open ++ ...> ++ } ++ ++ ++// write, but not read ++@ fops_w depends on maybe_stream && !has_read @ ++identifier fops0.fops, openfunc; ++identifier stream_writer.writestream; ++@@ ++ struct file_operations fops = { ++ .open = openfunc, ++ .write = writestream, ++ }; ++ ++@ report_w depends on report @ ++identifier fops_w.openfunc; ++position p1; ++@@ ++ openfunc(...) { ++ <... ++ nonseekable_open@p1 ++ ...> ++ } ++ ++@ script:python depends on report @ ++fops << fops0.fops; ++p << report_w.p1; ++@@ ++coccilib.report.print_report(p[0], ++ "WARNING: %s: .write() has stream semantic; safe to change nonseekable_open -> stream_open." % (fops,)) ++ ++@ explain_w depends on explain @ ++identifier fops_w.openfunc; ++@@ ++ openfunc(...) { ++ <... ++- nonseekable_open +++ nonseekable_open /* write only */ ++ ...> ++ } ++ ++@ patch_w depends on patch @ ++identifier fops_w.openfunc; ++@@ ++ openfunc(...) { ++ <... ++- nonseekable_open +++ stream_open ++ ...> ++ } ++ ++ ++// no read, no write - don't change anything +diff --git a/security/selinux/avc.c b/security/selinux/avc.c +index 635e5c1e3e48..5de18a6d5c3f 100644 +--- a/security/selinux/avc.c ++++ b/security/selinux/avc.c +@@ -838,6 +838,7 @@ out: + * @ssid,@tsid,@tclass : identifier of an AVC entry + * @seqno : sequence number when decision was made + * @xpd: extended_perms_decision to be added to the node ++ * @flags: the AVC_* flags, e.g. AVC_NONBLOCKING, AVC_EXTENDED_PERMS, or 0. + * + * if a valid AVC entry doesn't exist,this function returns -ENOENT. + * if kmalloc() called internal returns NULL, this function returns -ENOMEM. +@@ -856,6 +857,23 @@ static int avc_update_node(struct selinux_avc *avc, + struct hlist_head *head; + spinlock_t *lock; + ++ /* ++ * If we are in a non-blocking code path, e.g. VFS RCU walk, ++ * then we must not add permissions to a cache entry ++ * because we cannot safely audit the denial. Otherwise, ++ * during the subsequent blocking retry (e.g. VFS ref walk), we ++ * will find the permissions already granted in the cache entry ++ * and won't audit anything at all, leading to silent denials in ++ * permissive mode that only appear when in enforcing mode. ++ * ++ * See the corresponding handling in slow_avc_audit(), and the ++ * logic in selinux_inode_follow_link and selinux_inode_permission ++ * for the VFS MAY_NOT_BLOCK flag, which is transliterated into ++ * AVC_NONBLOCKING for avc_has_perm_noaudit(). ++ */ ++ if (flags & AVC_NONBLOCKING) ++ return 0; ++ + node = avc_alloc_node(avc); + if (!node) { + rc = -ENOMEM; +@@ -1115,7 +1133,7 @@ decision: + * @tsid: target security identifier + * @tclass: target security class + * @requested: requested permissions, interpreted based on @tclass +- * @flags: AVC_STRICT or 0 ++ * @flags: AVC_STRICT, AVC_NONBLOCKING, or 0 + * @avd: access vector decisions + * + * Check the AVC to determine whether the @requested permissions are granted +@@ -1199,7 +1217,8 @@ int avc_has_perm_flags(struct selinux_state *state, + struct av_decision avd; + int rc, rc2; + +- rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, 0, ++ rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, ++ (flags & MAY_NOT_BLOCK) ? AVC_NONBLOCKING : 0, + &avd); + + rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc, +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index 4337b6d9369e..cba19b8c3e51 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -497,16 +497,10 @@ static int may_context_mount_inode_relabel(u32 sid, + return rc; + } + +-static int selinux_is_sblabel_mnt(struct super_block *sb) ++static int selinux_is_genfs_special_handling(struct super_block *sb) + { +- struct superblock_security_struct *sbsec = sb->s_security; +- +- return sbsec->behavior == SECURITY_FS_USE_XATTR || +- sbsec->behavior == SECURITY_FS_USE_TRANS || +- sbsec->behavior == SECURITY_FS_USE_TASK || +- sbsec->behavior == SECURITY_FS_USE_NATIVE || +- /* Special handling. Genfs but also in-core setxattr handler */ +- !strcmp(sb->s_type->name, "sysfs") || ++ /* Special handling. Genfs but also in-core setxattr handler */ ++ return !strcmp(sb->s_type->name, "sysfs") || + !strcmp(sb->s_type->name, "pstore") || + !strcmp(sb->s_type->name, "debugfs") || + !strcmp(sb->s_type->name, "tracefs") || +@@ -516,6 +510,34 @@ static int selinux_is_sblabel_mnt(struct super_block *sb) + !strcmp(sb->s_type->name, "cgroup2"))); + } + ++static int selinux_is_sblabel_mnt(struct super_block *sb) ++{ ++ struct superblock_security_struct *sbsec = sb->s_security; ++ ++ /* ++ * IMPORTANT: Double-check logic in this function when adding a new ++ * SECURITY_FS_USE_* definition! ++ */ ++ BUILD_BUG_ON(SECURITY_FS_USE_MAX != 7); ++ ++ switch (sbsec->behavior) { ++ case SECURITY_FS_USE_XATTR: ++ case SECURITY_FS_USE_TRANS: ++ case SECURITY_FS_USE_TASK: ++ case SECURITY_FS_USE_NATIVE: ++ return 1; ++ ++ case SECURITY_FS_USE_GENFS: ++ return selinux_is_genfs_special_handling(sb); ++ ++ /* Never allow relabeling on context mounts */ ++ case SECURITY_FS_USE_MNTPOINT: ++ case SECURITY_FS_USE_NONE: ++ default: ++ return 0; ++ } ++} ++ + static int sb_finish_set_opts(struct super_block *sb) + { + struct superblock_security_struct *sbsec = sb->s_security; +@@ -3199,7 +3221,9 @@ static int selinux_inode_permission(struct inode *inode, int mask) + return PTR_ERR(isec); + + rc = avc_has_perm_noaudit(&selinux_state, +- sid, isec->sid, isec->sclass, perms, 0, &avd); ++ sid, isec->sid, isec->sclass, perms, ++ (flags & MAY_NOT_BLOCK) ? AVC_NONBLOCKING : 0, ++ &avd); + audited = avc_audit_required(perms, &avd, rc, + from_access ? FILE__AUDIT_ACCESS : 0, + &denied); +diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h +index ef899bcfd2cb..74ea50977c20 100644 +--- a/security/selinux/include/avc.h ++++ b/security/selinux/include/avc.h +@@ -142,6 +142,7 @@ static inline int avc_audit(struct selinux_state *state, + + #define AVC_STRICT 1 /* Ignore permissive mode. */ + #define AVC_EXTENDED_PERMS 2 /* update extended permissions */ ++#define AVC_NONBLOCKING 4 /* non blocking */ + int avc_has_perm_noaudit(struct selinux_state *state, + u32 ssid, u32 tsid, + u16 tclass, u32 requested, +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 0a745d677b1c..75a0be2aa9c2 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -5448,6 +5448,8 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec, + return; + + spec->gen.preferred_dacs = preferred_pairs; ++ spec->gen.auto_mute_via_amp = 1; ++ codec->power_save_node = 0; + } + + /* The DAC of NID 0x3 will introduce click/pop noise on headphones, so invalidate it */ +@@ -7172,6 +7174,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { + {0x21, 0x02211020}), + SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + {0x21, 0x02211020}), ++ SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, ++ {0x12, 0x40000000}, ++ {0x14, 0x90170110}, ++ {0x21, 0x02211020}), + SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, + {0x14, 0x90170110}, + {0x21, 0x02211020}), +@@ -7445,6 +7451,13 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { + {0x12, 0x90a60130}, + {0x17, 0x90170110}, + {0x21, 0x04211020}), ++ SND_HDA_PIN_QUIRK(0x10ec0295, 0x1043, "ASUS", ALC294_FIXUP_ASUS_SPK, ++ {0x12, 0x90a60130}, ++ {0x17, 0x90170110}, ++ {0x21, 0x03211020}), ++ SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, ++ {0x14, 0x90170110}, ++ {0x21, 0x04211020}), + SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC295_STANDARD_PINS, + {0x17, 0x21014020}, +diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c +index 4d3ec295679d..a651fed62a27 100644 +--- a/sound/soc/codecs/wm_adsp.c ++++ b/sound/soc/codecs/wm_adsp.c +@@ -3441,8 +3441,6 @@ int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd) + } + } + +- wm_adsp_buffer_clear(compr->buf); +- + /* Trigger the IRQ at one fragment of data */ + ret = wm_adsp_buffer_write(compr->buf, + HOST_BUFFER_FIELD(high_water_mark), +@@ -3454,6 +3452,8 @@ int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd) + } + break; + case SNDRV_PCM_TRIGGER_STOP: ++ if (wm_adsp_compr_attached(compr)) ++ wm_adsp_buffer_clear(compr->buf); + break; + default: + ret = -EINVAL; +diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c +index f8a68bdb3885..b74bbee111c6 100644 +--- a/sound/soc/intel/boards/bytcr_rt5651.c ++++ b/sound/soc/intel/boards/bytcr_rt5651.c +@@ -267,7 +267,7 @@ static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = { + static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic_map[] = { + {"DMIC L1", NULL, "Internal Mic"}, + {"DMIC R1", NULL, "Internal Mic"}, +- {"IN3P", NULL, "Headset Mic"}, ++ {"IN2P", NULL, "Headset Mic"}, + }; + + static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_map[] = { +diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c +index 06fba9650ac4..85c4b6d8e89d 100644 +--- a/sound/soc/stm/stm32_sai_sub.c ++++ b/sound/soc/stm/stm32_sai_sub.c +@@ -1194,7 +1194,6 @@ static int stm32_sai_sub_dais_init(struct platform_device *pdev, + if (!sai->cpu_dai_drv) + return -ENOMEM; + +- sai->cpu_dai_drv->name = dev_name(&pdev->dev); + if (STM_SAI_IS_PLAYBACK(sai)) { + memcpy(sai->cpu_dai_drv, &stm32_sai_playback_dai, + sizeof(stm32_sai_playback_dai)); +@@ -1204,6 +1203,7 @@ static int stm32_sai_sub_dais_init(struct platform_device *pdev, + sizeof(stm32_sai_capture_dai)); + sai->cpu_dai_drv->capture.stream_name = sai->cpu_dai_drv->name; + } ++ sai->cpu_dai_drv->name = dev_name(&pdev->dev); + + return 0; + } diff --git a/patch/kernel/sunxi-next/patch-4.19.41-42.patch b/patch/kernel/sunxi-next/patch-4.19.41-42.patch new file mode 100644 index 0000000000..ad6da18234 --- /dev/null +++ b/patch/kernel/sunxi-next/patch-4.19.41-42.patch @@ -0,0 +1,4659 @@ +diff --git a/Makefile b/Makefile +index ba3b8504b689..914d69b9e3fd 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 4 + PATCHLEVEL = 19 +-SUBLEVEL = 41 ++SUBLEVEL = 42 + EXTRAVERSION = + NAME = "People's Front" + +diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h +index fd1e722f3821..c7e30a6ed56e 100644 +--- a/arch/arm64/include/asm/futex.h ++++ b/arch/arm64/include/asm/futex.h +@@ -23,26 +23,34 @@ + + #include + ++#define FUTEX_MAX_LOOPS 128 /* What's the largest number you can think of? */ ++ + #define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg) \ + do { \ ++ unsigned int loops = FUTEX_MAX_LOOPS; \ ++ \ + uaccess_enable(); \ + asm volatile( \ + " prfm pstl1strm, %2\n" \ + "1: ldxr %w1, %2\n" \ + insn "\n" \ + "2: stlxr %w0, %w3, %2\n" \ +-" cbnz %w0, 1b\n" \ +-" dmb ish\n" \ ++" cbz %w0, 3f\n" \ ++" sub %w4, %w4, %w0\n" \ ++" cbnz %w4, 1b\n" \ ++" mov %w0, %w7\n" \ + "3:\n" \ ++" dmb ish\n" \ + " .pushsection .fixup,\"ax\"\n" \ + " .align 2\n" \ +-"4: mov %w0, %w5\n" \ ++"4: mov %w0, %w6\n" \ + " b 3b\n" \ + " .popsection\n" \ + _ASM_EXTABLE(1b, 4b) \ + _ASM_EXTABLE(2b, 4b) \ +- : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \ +- : "r" (oparg), "Ir" (-EFAULT) \ ++ : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp), \ ++ "+r" (loops) \ ++ : "r" (oparg), "Ir" (-EFAULT), "Ir" (-EAGAIN) \ + : "memory"); \ + uaccess_disable(); \ + } while (0) +@@ -57,23 +65,23 @@ arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *_uaddr) + + switch (op) { + case FUTEX_OP_SET: +- __futex_atomic_op("mov %w3, %w4", ++ __futex_atomic_op("mov %w3, %w5", + ret, oldval, uaddr, tmp, oparg); + break; + case FUTEX_OP_ADD: +- __futex_atomic_op("add %w3, %w1, %w4", ++ __futex_atomic_op("add %w3, %w1, %w5", + ret, oldval, uaddr, tmp, oparg); + break; + case FUTEX_OP_OR: +- __futex_atomic_op("orr %w3, %w1, %w4", ++ __futex_atomic_op("orr %w3, %w1, %w5", + ret, oldval, uaddr, tmp, oparg); + break; + case FUTEX_OP_ANDN: +- __futex_atomic_op("and %w3, %w1, %w4", ++ __futex_atomic_op("and %w3, %w1, %w5", + ret, oldval, uaddr, tmp, ~oparg); + break; + case FUTEX_OP_XOR: +- __futex_atomic_op("eor %w3, %w1, %w4", ++ __futex_atomic_op("eor %w3, %w1, %w5", + ret, oldval, uaddr, tmp, oparg); + break; + default: +@@ -93,6 +101,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *_uaddr, + u32 oldval, u32 newval) + { + int ret = 0; ++ unsigned int loops = FUTEX_MAX_LOOPS; + u32 val, tmp; + u32 __user *uaddr; + +@@ -104,20 +113,24 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *_uaddr, + asm volatile("// futex_atomic_cmpxchg_inatomic\n" + " prfm pstl1strm, %2\n" + "1: ldxr %w1, %2\n" +-" sub %w3, %w1, %w4\n" +-" cbnz %w3, 3f\n" +-"2: stlxr %w3, %w5, %2\n" +-" cbnz %w3, 1b\n" +-" dmb ish\n" ++" sub %w3, %w1, %w5\n" ++" cbnz %w3, 4f\n" ++"2: stlxr %w3, %w6, %2\n" ++" cbz %w3, 3f\n" ++" sub %w4, %w4, %w3\n" ++" cbnz %w4, 1b\n" ++" mov %w0, %w8\n" + "3:\n" ++" dmb ish\n" ++"4:\n" + " .pushsection .fixup,\"ax\"\n" +-"4: mov %w0, %w6\n" +-" b 3b\n" ++"5: mov %w0, %w7\n" ++" b 4b\n" + " .popsection\n" +- _ASM_EXTABLE(1b, 4b) +- _ASM_EXTABLE(2b, 4b) +- : "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp) +- : "r" (oldval), "r" (newval), "Ir" (-EFAULT) ++ _ASM_EXTABLE(1b, 5b) ++ _ASM_EXTABLE(2b, 5b) ++ : "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp), "+r" (loops) ++ : "r" (oldval), "r" (newval), "Ir" (-EFAULT), "Ir" (-EAGAIN) + : "memory"); + uaccess_disable(); + +diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c +index eb6c0d582626..2c1e30ca7ee4 100644 +--- a/arch/mips/kernel/kgdb.c ++++ b/arch/mips/kernel/kgdb.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + + static struct hard_trap_info { + unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */ +@@ -214,7 +215,7 @@ static void kgdb_call_nmi_hook(void *ignored) + old_fs = get_fs(); + set_fs(get_ds()); + +- kgdb_nmicallback(raw_smp_processor_id(), NULL); ++ kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); + + set_fs(old_fs); + } +diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c +index 3dd204d1dd19..f9958ad4d335 100644 +--- a/arch/x86/events/intel/core.c ++++ b/arch/x86/events/intel/core.c +@@ -3068,7 +3068,7 @@ static int intel_pmu_hw_config(struct perf_event *event) + return ret; + + if (event->attr.precise_ip) { +- if (!event->attr.freq) { ++ if (!(event->attr.freq || event->attr.wakeup_events)) { + event->hw.flags |= PERF_X86_EVENT_AUTO_RELOAD; + if (!(event->attr.sample_type & + ~intel_pmu_large_pebs_flags(event))) +@@ -3447,6 +3447,12 @@ static void intel_pmu_cpu_starting(int cpu) + + cpuc->lbr_sel = NULL; + ++ if (x86_pmu.flags & PMU_FL_TFA) { ++ WARN_ON_ONCE(cpuc->tfa_shadow); ++ cpuc->tfa_shadow = ~0ULL; ++ intel_set_tfa(cpuc, false); ++ } ++ + if (x86_pmu.version > 1) + flip_smm_bit(&x86_pmu.attr_freeze_on_smi); + +diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c +index 23752dc99b00..dd64f586679e 100644 +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -446,6 +446,8 @@ static int init_vq(struct virtio_blk *vblk) + if (err) + num_vqs = 1; + ++ num_vqs = min_t(unsigned int, nr_cpu_ids, num_vqs); ++ + vblk->vqs = kmalloc_array(num_vqs, sizeof(*vblk->vqs), GFP_KERNEL); + if (!vblk->vqs) + return -ENOMEM; +diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c +index 6628ffa31383..4d4f6d842c31 100644 +--- a/drivers/clk/meson/gxbb.c ++++ b/drivers/clk/meson/gxbb.c +@@ -1571,6 +1571,7 @@ static struct clk_regmap gxbb_vdec_1_div = { + .offset = HHI_VDEC_CLK_CNTL, + .shift = 0, + .width = 7, ++ .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_1_div", +@@ -1616,6 +1617,7 @@ static struct clk_regmap gxbb_vdec_hevc_div = { + .offset = HHI_VDEC2_CLK_CNTL, + .shift = 16, + .width = 7, ++ .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_hevc_div", +diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c +index 75491fc841a6..0df16eb1eb3c 100644 +--- a/drivers/cpufreq/armada-37xx-cpufreq.c ++++ b/drivers/cpufreq/armada-37xx-cpufreq.c +@@ -359,11 +359,11 @@ static int __init armada37xx_cpufreq_driver_init(void) + struct armada_37xx_dvfs *dvfs; + struct platform_device *pdev; + unsigned long freq; +- unsigned int cur_frequency; ++ unsigned int cur_frequency, base_frequency; + struct regmap *nb_pm_base, *avs_base; + struct device *cpu_dev; + int load_lvl, ret; +- struct clk *clk; ++ struct clk *clk, *parent; + + nb_pm_base = + syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm"); +@@ -399,6 +399,22 @@ static int __init armada37xx_cpufreq_driver_init(void) + return PTR_ERR(clk); + } + ++ parent = clk_get_parent(clk); ++ if (IS_ERR(parent)) { ++ dev_err(cpu_dev, "Cannot get parent clock for CPU0\n"); ++ clk_put(clk); ++ return PTR_ERR(parent); ++ } ++ ++ /* Get parent CPU frequency */ ++ base_frequency = clk_get_rate(parent); ++ ++ if (!base_frequency) { ++ dev_err(cpu_dev, "Failed to get parent clock rate for CPU\n"); ++ clk_put(clk); ++ return -EINVAL; ++ } ++ + /* Get nominal (current) CPU frequency */ + cur_frequency = clk_get_rate(clk); + if (!cur_frequency) { +@@ -431,7 +447,7 @@ static int __init armada37xx_cpufreq_driver_init(void) + for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR; + load_lvl++) { + unsigned long u_volt = avs_map[dvfs->avs[load_lvl]] * 1000; +- freq = cur_frequency / dvfs->divider[load_lvl]; ++ freq = base_frequency / dvfs->divider[load_lvl]; + ret = dev_pm_opp_add(cpu_dev, freq, u_volt); + if (ret) + goto remove_opp; +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 2b8b892eb846..76ee2de43ea6 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -4028,6 +4028,7 @@ static void handle_cursor_update(struct drm_plane *plane, + amdgpu_crtc->cursor_width = plane->state->crtc_w; + amdgpu_crtc->cursor_height = plane->state->crtc_h; + ++ memset(&attributes, 0, sizeof(attributes)); + attributes.address.high_part = upper_32_bits(address); + attributes.address.low_part = lower_32_bits(address); + attributes.width = plane->state->crtc_w; +diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c +index 643f5edd68fe..62444a3a5742 100644 +--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c ++++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c +@@ -1473,7 +1473,6 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, + if (IS_ERR(regmap)) + ret = PTR_ERR(regmap); + if (ret) { +- ret = PTR_ERR(regmap); + dev_err(dev, + "Failed to get system configuration registers: %d\n", + ret); +@@ -1509,6 +1508,7 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, + of_node_put(remote); + + hdmi->ddc_adpt = of_find_i2c_adapter_by_node(i2c_np); ++ of_node_put(i2c_np); + if (!hdmi->ddc_adpt) { + dev_err(dev, "Failed to get ddc i2c adapter by node\n"); + return -EINVAL; +diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c +index 340383150fb9..ebf9c96d43ee 100644 +--- a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c ++++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c +@@ -175,6 +175,7 @@ static int hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) + REG_FLD_MOD(core->base, HDMI_CORE_SYS_INTR_UNMASK4, 0, 3, 3); + hdmi_wp_clear_irqenable(core->wp, HDMI_IRQ_CORE); + hdmi_wp_set_irqstatus(core->wp, HDMI_IRQ_CORE); ++ REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0, 5, 0); + hdmi4_core_disable(core); + return 0; + } +@@ -182,16 +183,24 @@ static int hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) + if (err) + return err; + ++ /* ++ * Initialize CEC clock divider: CEC needs 2MHz clock hence ++ * set the divider to 24 to get 48/24=2MHz clock ++ */ ++ REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0x18, 5, 0); ++ + /* Clear TX FIFO */ + if (!hdmi_cec_clear_tx_fifo(adap)) { + pr_err("cec-%s: could not clear TX FIFO\n", adap->name); +- return -EIO; ++ err = -EIO; ++ goto err_disable_clk; + } + + /* Clear RX FIFO */ + if (!hdmi_cec_clear_rx_fifo(adap)) { + pr_err("cec-%s: could not clear RX FIFO\n", adap->name); +- return -EIO; ++ err = -EIO; ++ goto err_disable_clk; + } + + /* Clear CEC interrupts */ +@@ -236,6 +245,12 @@ static int hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, temp); + } + return 0; ++ ++err_disable_clk: ++ REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0, 5, 0); ++ hdmi4_core_disable(core); ++ ++ return err; + } + + static int hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) +@@ -333,11 +348,8 @@ int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core, + return ret; + core->wp = wp; + +- /* +- * Initialize CEC clock divider: CEC needs 2MHz clock hence +- * set the devider to 24 to get 48/24=2MHz clock +- */ +- REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0x18, 5, 0); ++ /* Disable clock initially, hdmi_cec_adap_enable() manages it */ ++ REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0, 5, 0); + + ret = cec_register_adapter(core->adap, &pdev->dev); + if (ret < 0) { +diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c +index adcdf946c365..dfbcd1ad81a5 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c ++++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c +@@ -217,7 +217,7 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master, + + err_unregister_gates: + for (i = 0; i < CLK_NUM; i++) +- if (clk_data->hws[i]) ++ if (!IS_ERR_OR_NULL(clk_data->hws[i])) + clk_hw_unregister_gate(clk_data->hws[i]); + clk_disable_unprepare(tcon_top->bus); + err_assert_reset: +@@ -235,7 +235,8 @@ static void sun8i_tcon_top_unbind(struct device *dev, struct device *master, + + of_clk_del_provider(dev->of_node); + for (i = 0; i < CLK_NUM; i++) +- clk_hw_unregister_gate(clk_data->hws[i]); ++ if (clk_data->hws[i]) ++ clk_hw_unregister_gate(clk_data->hws[i]); + + clk_disable_unprepare(tcon_top->bus); + reset_control_assert(tcon_top->rst); +diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c +index 748a1c4172a6..8e923e70e594 100644 +--- a/drivers/hv/hv.c ++++ b/drivers/hv/hv.c +@@ -402,7 +402,6 @@ int hv_synic_cleanup(unsigned int cpu) + + clockevents_unbind_device(hv_cpu->clk_evt, cpu); + hv_ce_shutdown(hv_cpu->clk_evt); +- put_cpu_ptr(hv_cpu); + } + + hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64); +diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c +index 1cf6290d6435..70f2cb90adc5 100644 +--- a/drivers/hwtracing/intel_th/pci.c ++++ b/drivers/hwtracing/intel_th/pci.c +@@ -165,6 +165,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = { + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x34a6), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, ++ { ++ /* Comet Lake */ ++ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x02a6), ++ .driver_data = (kernel_ulong_t)&intel_th_2x, ++ }, + { 0 }, + }; + +diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c +index 902d12d6d88b..b12c8ff8ed66 100644 +--- a/drivers/infiniband/hw/hfi1/chip.c ++++ b/drivers/infiniband/hw/hfi1/chip.c +@@ -13388,7 +13388,7 @@ static int set_up_context_variables(struct hfi1_devdata *dd) + int total_contexts; + int ret; + unsigned ngroups; +- int qos_rmt_count; ++ int rmt_count; + int user_rmt_reduced; + u32 n_usr_ctxts; + u32 send_contexts = chip_send_contexts(dd); +@@ -13450,10 +13450,20 @@ static int set_up_context_variables(struct hfi1_devdata *dd) + n_usr_ctxts = rcv_contexts - total_contexts; + } + +- /* each user context requires an entry in the RMT */ +- qos_rmt_count = qos_rmt_entries(dd, NULL, NULL); +- if (qos_rmt_count + n_usr_ctxts > NUM_MAP_ENTRIES) { +- user_rmt_reduced = NUM_MAP_ENTRIES - qos_rmt_count; ++ /* ++ * The RMT entries are currently allocated as shown below: ++ * 1. QOS (0 to 128 entries); ++ * 2. FECN for PSM (num_user_contexts + num_vnic_contexts); ++ * 3. VNIC (num_vnic_contexts). ++ * It should be noted that PSM FECN oversubscribe num_vnic_contexts ++ * entries of RMT because both VNIC and PSM could allocate any receive ++ * context between dd->first_dyn_alloc_text and dd->num_rcv_contexts, ++ * and PSM FECN must reserve an RMT entry for each possible PSM receive ++ * context. ++ */ ++ rmt_count = qos_rmt_entries(dd, NULL, NULL) + (num_vnic_contexts * 2); ++ if (rmt_count + n_usr_ctxts > NUM_MAP_ENTRIES) { ++ user_rmt_reduced = NUM_MAP_ENTRIES - rmt_count; + dd_dev_err(dd, + "RMT size is reducing the number of user receive contexts from %u to %d\n", + n_usr_ctxts, +@@ -14441,9 +14451,11 @@ static void init_user_fecn_handling(struct hfi1_devdata *dd, + u64 reg; + int i, idx, regoff, regidx; + u8 offset; ++ u32 total_cnt; + + /* there needs to be enough room in the map table */ +- if (rmt->used + dd->num_user_contexts >= NUM_MAP_ENTRIES) { ++ total_cnt = dd->num_rcv_contexts - dd->first_dyn_alloc_ctxt; ++ if (rmt->used + total_cnt >= NUM_MAP_ENTRIES) { + dd_dev_err(dd, "User FECN handling disabled - too many user contexts allocated\n"); + return; + } +@@ -14497,7 +14509,7 @@ static void init_user_fecn_handling(struct hfi1_devdata *dd, + /* add rule 1 */ + add_rsm_rule(dd, RSM_INS_FECN, &rrd); + +- rmt->used += dd->num_user_contexts; ++ rmt->used += total_cnt; + } + + /* Initialize RSM for VNIC */ +diff --git a/drivers/infiniband/hw/hfi1/rc.c b/drivers/infiniband/hw/hfi1/rc.c +index 6f013a565353..770c78c65730 100644 +--- a/drivers/infiniband/hw/hfi1/rc.c ++++ b/drivers/infiniband/hw/hfi1/rc.c +@@ -2303,7 +2303,7 @@ send_last: + update_ack_queue(qp, next); + } + e = &qp->s_ack_queue[qp->r_head_ack_queue]; +- if (e->opcode == OP(RDMA_READ_REQUEST) && e->rdma_sge.mr) { ++ if (e->rdma_sge.mr) { + rvt_put_mr(e->rdma_sge.mr); + e->rdma_sge.mr = NULL; + } +@@ -2377,7 +2377,7 @@ send_last: + update_ack_queue(qp, next); + } + e = &qp->s_ack_queue[qp->r_head_ack_queue]; +- if (e->opcode == OP(RDMA_READ_REQUEST) && e->rdma_sge.mr) { ++ if (e->rdma_sge.mr) { + rvt_put_mr(e->rdma_sge.mr); + e->rdma_sge.mr = NULL; + } +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index f6faefed96e8..a73d388b7093 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -745,6 +745,8 @@ void *hns_roce_table_find(struct hns_roce_dev *hr_dev, + idx_offset = (obj & (table->num_obj - 1)) % obj_per_chunk; + dma_offset = offset = idx_offset * table->obj_size; + } else { ++ u32 seg_size = 64; /* 8 bytes per BA and 8 BA per segment */ ++ + hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop); + /* mtt mhop */ + i = mhop.l0_idx; +@@ -756,8 +758,8 @@ void *hns_roce_table_find(struct hns_roce_dev *hr_dev, + hem_idx = i; + + hem = table->hem[hem_idx]; +- dma_offset = offset = (obj & (table->num_obj - 1)) * +- table->obj_size % mhop.bt_chunk_size; ++ dma_offset = offset = (obj & (table->num_obj - 1)) * seg_size % ++ mhop.bt_chunk_size; + if (mhop.hop_num == 2) + dma_offset = offset = 0; + } +diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c +index eb26a5f6fc58..41a538d23b80 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_mr.c ++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c +@@ -707,7 +707,6 @@ static int hns_roce_write_mtt_chunk(struct hns_roce_dev *hr_dev, + struct hns_roce_hem_table *table; + dma_addr_t dma_handle; + __le64 *mtts; +- u32 s = start_index * sizeof(u64); + u32 bt_page_size; + u32 i; + +@@ -730,7 +729,8 @@ static int hns_roce_write_mtt_chunk(struct hns_roce_dev *hr_dev, + table = &hr_dev->mr_table.mtt_cqe_table; + + mtts = hns_roce_table_find(hr_dev, table, +- mtt->first_seg + s / hr_dev->caps.mtt_entry_sz, ++ mtt->first_seg + ++ start_index / HNS_ROCE_MTT_ENTRY_PER_SEG, + &dma_handle); + if (!mtts) + return -ENOMEM; +diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c +index a5719899f49a..ed99f0a08dc4 100644 +--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c ++++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c +@@ -1123,6 +1123,8 @@ static void pvrdma_pci_remove(struct pci_dev *pdev) + pvrdma_page_dir_cleanup(dev, &dev->cq_pdir); + pvrdma_page_dir_cleanup(dev, &dev->async_pdir); + pvrdma_free_slots(dev); ++ dma_free_coherent(&pdev->dev, sizeof(*dev->dsr), dev->dsr, ++ dev->dsrbase); + + iounmap(dev->regs); + kfree(dev->sgid_tbl); +diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c +index be3801d43d48..3a1d30304f7e 100644 +--- a/drivers/iommu/amd_iommu_init.c ++++ b/drivers/iommu/amd_iommu_init.c +@@ -356,7 +356,7 @@ static void iommu_write_l2(struct amd_iommu *iommu, u8 address, u32 val) + static void iommu_set_exclusion_range(struct amd_iommu *iommu) + { + u64 start = iommu->exclusion_start & PAGE_MASK; +- u64 limit = (start + iommu->exclusion_length) & PAGE_MASK; ++ u64 limit = (start + iommu->exclusion_length - 1) & PAGE_MASK; + u64 entry; + + if (!iommu->exclusion_start) +diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +index b7dd4e3c760d..6d690678c20e 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +@@ -140,7 +140,7 @@ static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode, + p->des0 |= cpu_to_le32(RDES0_OWN); + + bfsize1 = min(bfsize, BUF_SIZE_2KiB - 1); +- p->des1 |= cpu_to_le32(bfsize & RDES1_BUFFER1_SIZE_MASK); ++ p->des1 |= cpu_to_le32(bfsize1 & RDES1_BUFFER1_SIZE_MASK); + + if (mode == STMMAC_CHAIN_MODE) + ndesc_rx_set_on_chain(p, end); +diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c +index 9375fa705d82..67dec8860bf3 100644 +--- a/drivers/nvme/host/fc.c ++++ b/drivers/nvme/host/fc.c +@@ -1844,7 +1844,7 @@ nvme_fc_init_queue(struct nvme_fc_ctrl *ctrl, int idx) + memset(queue, 0, sizeof(*queue)); + queue->ctrl = ctrl; + queue->qnum = idx; +- atomic_set(&queue->csn, 1); ++ atomic_set(&queue->csn, 0); + queue->dev = ctrl->dev; + + if (idx > 0) +@@ -1886,7 +1886,7 @@ nvme_fc_free_queue(struct nvme_fc_queue *queue) + */ + + queue->connection_id = 0; +- atomic_set(&queue->csn, 1); ++ atomic_set(&queue->csn, 0); + } + + static void +@@ -2182,7 +2182,6 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue, + { + struct nvme_fc_cmd_iu *cmdiu = &op->cmd_iu; + struct nvme_command *sqe = &cmdiu->sqe; +- u32 csn; + int ret, opstate; + + /* +@@ -2197,8 +2196,6 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue, + + /* format the FC-NVME CMD IU and fcp_req */ + cmdiu->connection_id = cpu_to_be64(queue->connection_id); +- csn = atomic_inc_return(&queue->csn); +- cmdiu->csn = cpu_to_be32(csn); + cmdiu->data_len = cpu_to_be32(data_len); + switch (io_dir) { + case NVMEFC_FCP_WRITE: +@@ -2256,11 +2253,24 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue, + if (!(op->flags & FCOP_FLAGS_AEN)) + blk_mq_start_request(op->rq); + ++ cmdiu->csn = cpu_to_be32(atomic_inc_return(&queue->csn)); + ret = ctrl->lport->ops->fcp_io(&ctrl->lport->localport, + &ctrl->rport->remoteport, + queue->lldd_handle, &op->fcp_req); + + if (ret) { ++ /* ++ * If the lld fails to send the command is there an issue with ++ * the csn value? If the command that fails is the Connect, ++ * no - as the connection won't be live. If it is a command ++ * post-connect, it's possible a gap in csn may be created. ++ * Does this matter? As Linux initiators don't send fused ++ * commands, no. The gap would exist, but as there's nothing ++ * that depends on csn order to be delivered on the target ++ * side, it shouldn't hurt. It would be difficult for a ++ * target to even detect the csn gap as it has no idea when the ++ * cmd with the csn was supposed to arrive. ++ */ + opstate = atomic_xchg(&op->state, FCPOP_STATE_COMPLETE); + __nvme_fc_fcpop_chk_teardowns(ctrl, op, opstate); + +diff --git a/drivers/platform/x86/pmc_atom.c b/drivers/platform/x86/pmc_atom.c +index eaec2d306481..c7039f52ad51 100644 +--- a/drivers/platform/x86/pmc_atom.c ++++ b/drivers/platform/x86/pmc_atom.c +@@ -396,7 +396,7 @@ static int pmc_dbgfs_register(struct pmc_dev *pmc) + * Some systems need one or more of their pmc_plt_clks to be + * marked as critical. + */ +-static const struct dmi_system_id critclk_systems[] __initconst = { ++static const struct dmi_system_id critclk_systems[] = { + { + .ident = "MPL CEC1x", + .matches = { +diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c +index dab0d3f9bee1..e09c7f360dbd 100644 +--- a/drivers/scsi/csiostor/csio_scsi.c ++++ b/drivers/scsi/csiostor/csio_scsi.c +@@ -1713,8 +1713,11 @@ csio_scsi_err_handler(struct csio_hw *hw, struct csio_ioreq *req) + } + + out: +- if (req->nsge > 0) ++ if (req->nsge > 0) { + scsi_dma_unmap(cmnd); ++ if (req->dcopy && (host_status == DID_OK)) ++ host_status = csio_scsi_copy_to_sgl(hw, req); ++ } + + cmnd->result = (((host_status) << 16) | scsi_status); + cmnd->scsi_done(cmnd); +diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c +index a1551ab33616..e9ecc667e3fb 100644 +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -48,17 +48,16 @@ static void smp_task_timedout(struct timer_list *t) + unsigned long flags; + + spin_lock_irqsave(&task->task_state_lock, flags); +- if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) ++ if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { + task->task_state_flags |= SAS_TASK_STATE_ABORTED; ++ complete(&task->slow_task->completion); ++ } + spin_unlock_irqrestore(&task->task_state_lock, flags); +- +- complete(&task->slow_task->completion); + } + + static void smp_task_done(struct sas_task *task) + { +- if (!del_timer(&task->slow_task->timer)) +- return; ++ del_timer(&task->slow_task->timer); + complete(&task->slow_task->completion); + } + +diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c +index 1a6ed9b0a249..cb19b12e7211 100644 +--- a/drivers/scsi/lpfc/lpfc_attr.c ++++ b/drivers/scsi/lpfc/lpfc_attr.c +@@ -117,7 +117,7 @@ static ssize_t + lpfc_drvr_version_show(struct device *dev, struct device_attribute *attr, + char *buf) + { +- return snprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n"); ++ return scnprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n"); + } + + /** +@@ -137,9 +137,9 @@ lpfc_enable_fip_show(struct device *dev, struct device_attribute *attr, + struct lpfc_hba *phba = vport->phba; + + if (phba->hba_flag & HBA_FIP_SUPPORT) +- return snprintf(buf, PAGE_SIZE, "1\n"); ++ return scnprintf(buf, PAGE_SIZE, "1\n"); + else +- return snprintf(buf, PAGE_SIZE, "0\n"); ++ return scnprintf(buf, PAGE_SIZE, "0\n"); + } + + static ssize_t +@@ -517,14 +517,15 @@ lpfc_bg_info_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- if (phba->cfg_enable_bg) ++ if (phba->cfg_enable_bg) { + if (phba->sli3_options & LPFC_SLI3_BG_ENABLED) +- return snprintf(buf, PAGE_SIZE, "BlockGuard Enabled\n"); ++ return scnprintf(buf, PAGE_SIZE, ++ "BlockGuard Enabled\n"); + else +- return snprintf(buf, PAGE_SIZE, ++ return scnprintf(buf, PAGE_SIZE, + "BlockGuard Not Supported\n"); +- else +- return snprintf(buf, PAGE_SIZE, ++ } else ++ return scnprintf(buf, PAGE_SIZE, + "BlockGuard Disabled\n"); + } + +@@ -536,7 +537,7 @@ lpfc_bg_guard_err_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%llu\n", ++ return scnprintf(buf, PAGE_SIZE, "%llu\n", + (unsigned long long)phba->bg_guard_err_cnt); + } + +@@ -548,7 +549,7 @@ lpfc_bg_apptag_err_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%llu\n", ++ return scnprintf(buf, PAGE_SIZE, "%llu\n", + (unsigned long long)phba->bg_apptag_err_cnt); + } + +@@ -560,7 +561,7 @@ lpfc_bg_reftag_err_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%llu\n", ++ return scnprintf(buf, PAGE_SIZE, "%llu\n", + (unsigned long long)phba->bg_reftag_err_cnt); + } + +@@ -578,7 +579,7 @@ lpfc_info_show(struct device *dev, struct device_attribute *attr, + { + struct Scsi_Host *host = class_to_shost(dev); + +- return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host)); ++ return scnprintf(buf, PAGE_SIZE, "%s\n", lpfc_info(host)); + } + + /** +@@ -597,7 +598,7 @@ lpfc_serialnum_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber); ++ return scnprintf(buf, PAGE_SIZE, "%s\n", phba->SerialNumber); + } + + /** +@@ -619,7 +620,7 @@ lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr, + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; +- return snprintf(buf, PAGE_SIZE, "%d\n",phba->temp_sensor_support); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", phba->temp_sensor_support); + } + + /** +@@ -638,7 +639,7 @@ lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc); ++ return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ModelDesc); + } + + /** +@@ -657,7 +658,7 @@ lpfc_modelname_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName); ++ return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ModelName); + } + + /** +@@ -676,7 +677,7 @@ lpfc_programtype_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType); ++ return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ProgramType); + } + + /** +@@ -694,7 +695,7 @@ lpfc_mlomgmt_show(struct device *dev, struct device_attribute *attr, char *buf) + struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%d\n", ++ return scnprintf(buf, PAGE_SIZE, "%d\n", + (phba->sli.sli_flag & LPFC_MENLO_MAINT)); + } + +@@ -714,7 +715,7 @@ lpfc_vportnum_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port); ++ return scnprintf(buf, PAGE_SIZE, "%s\n", phba->Port); + } + + /** +@@ -742,10 +743,10 @@ lpfc_fwrev_show(struct device *dev, struct device_attribute *attr, + sli_family = phba->sli4_hba.pc_sli4_params.sli_family; + + if (phba->sli_rev < LPFC_SLI_REV4) +- len = snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", ++ len = scnprintf(buf, PAGE_SIZE, "%s, sli-%d\n", + fwrev, phba->sli_rev); + else +- len = snprintf(buf, PAGE_SIZE, "%s, sli-%d:%d:%x\n", ++ len = scnprintf(buf, PAGE_SIZE, "%s, sli-%d:%d:%x\n", + fwrev, phba->sli_rev, if_type, sli_family); + + return len; +@@ -769,7 +770,7 @@ lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf) + lpfc_vpd_t *vp = &phba->vpd; + + lpfc_jedec_to_ascii(vp->rev.biuRev, hdw); +- return snprintf(buf, PAGE_SIZE, "%s\n", hdw); ++ return scnprintf(buf, PAGE_SIZE, "%s\n", hdw); + } + + /** +@@ -790,10 +791,11 @@ lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr, + char fwrev[FW_REV_STR_SIZE]; + + if (phba->sli_rev < LPFC_SLI_REV4) +- return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion); ++ return scnprintf(buf, PAGE_SIZE, "%s\n", ++ phba->OptionROMVersion); + + lpfc_decode_firmware_rev(phba, fwrev, 1); +- return snprintf(buf, PAGE_SIZE, "%s\n", fwrev); ++ return scnprintf(buf, PAGE_SIZE, "%s\n", fwrev); + } + + /** +@@ -824,20 +826,20 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr, + case LPFC_LINK_DOWN: + case LPFC_HBA_ERROR: + if (phba->hba_flag & LINK_DISABLED) +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Link Down - User disabled\n"); + else +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Link Down\n"); + break; + case LPFC_LINK_UP: + case LPFC_CLEAR_LA: + case LPFC_HBA_READY: +- len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - "); ++ len += scnprintf(buf + len, PAGE_SIZE-len, "Link Up - "); + + switch (vport->port_state) { + case LPFC_LOCAL_CFG_LINK: +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Configuring Link\n"); + break; + case LPFC_FDISC: +@@ -847,38 +849,40 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr, + case LPFC_NS_QRY: + case LPFC_BUILD_DISC_LIST: + case LPFC_DISC_AUTH: +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "Discovery\n"); + break; + case LPFC_VPORT_READY: +- len += snprintf(buf + len, PAGE_SIZE - len, "Ready\n"); ++ len += scnprintf(buf + len, PAGE_SIZE - len, ++ "Ready\n"); + break; + + case LPFC_VPORT_FAILED: +- len += snprintf(buf + len, PAGE_SIZE - len, "Failed\n"); ++ len += scnprintf(buf + len, PAGE_SIZE - len, ++ "Failed\n"); + break; + + case LPFC_VPORT_UNKNOWN: +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "Unknown\n"); + break; + } + if (phba->sli.sli_flag & LPFC_MENLO_MAINT) +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + " Menlo Maint Mode\n"); + else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { + if (vport->fc_flag & FC_PUBLIC_LOOP) +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + " Public Loop\n"); + else +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + " Private Loop\n"); + } else { + if (vport->fc_flag & FC_FABRIC) +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + " Fabric\n"); + else +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + " Point-2-Point\n"); + } + } +@@ -903,15 +907,15 @@ lpfc_sli4_protocol_show(struct device *dev, struct device_attribute *attr, + struct lpfc_hba *phba = vport->phba; + + if (phba->sli_rev < LPFC_SLI_REV4) +- return snprintf(buf, PAGE_SIZE, "fc\n"); ++ return scnprintf(buf, PAGE_SIZE, "fc\n"); + + if (phba->sli4_hba.lnk_info.lnk_dv == LPFC_LNK_DAT_VAL) { + if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_GE) +- return snprintf(buf, PAGE_SIZE, "fcoe\n"); ++ return scnprintf(buf, PAGE_SIZE, "fcoe\n"); + if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) +- return snprintf(buf, PAGE_SIZE, "fc\n"); ++ return scnprintf(buf, PAGE_SIZE, "fc\n"); + } +- return snprintf(buf, PAGE_SIZE, "unknown\n"); ++ return scnprintf(buf, PAGE_SIZE, "unknown\n"); + } + + /** +@@ -931,7 +935,7 @@ lpfc_oas_supported_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%d\n", ++ return scnprintf(buf, PAGE_SIZE, "%d\n", + phba->sli4_hba.pc_sli4_params.oas_supported); + } + +@@ -989,7 +993,7 @@ lpfc_num_discovered_ports_show(struct device *dev, + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + +- return snprintf(buf, PAGE_SIZE, "%d\n", ++ return scnprintf(buf, PAGE_SIZE, "%d\n", + vport->fc_map_cnt + vport->fc_unmap_cnt); + } + +@@ -1427,7 +1431,7 @@ lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt); + } + + /** +@@ -1456,7 +1460,7 @@ lpfc_board_mode_show(struct device *dev, struct device_attribute *attr, + else + state = "online"; + +- return snprintf(buf, PAGE_SIZE, "%s\n", state); ++ return scnprintf(buf, PAGE_SIZE, "%s\n", state); + } + + /** +@@ -1669,8 +1673,8 @@ lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr, + uint32_t cnt; + + if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL, NULL, NULL)) +- return snprintf(buf, PAGE_SIZE, "%d\n", cnt); +- return snprintf(buf, PAGE_SIZE, "Unknown\n"); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", cnt); ++ return scnprintf(buf, PAGE_SIZE, "Unknown\n"); + } + + /** +@@ -1697,8 +1701,8 @@ lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr, + uint32_t cnt, acnt; + + if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt, NULL, NULL)) +- return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); +- return snprintf(buf, PAGE_SIZE, "Unknown\n"); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); ++ return scnprintf(buf, PAGE_SIZE, "Unknown\n"); + } + + /** +@@ -1725,8 +1729,8 @@ lpfc_max_xri_show(struct device *dev, struct device_attribute *attr, + uint32_t cnt; + + if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL, NULL, NULL)) +- return snprintf(buf, PAGE_SIZE, "%d\n", cnt); +- return snprintf(buf, PAGE_SIZE, "Unknown\n"); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", cnt); ++ return scnprintf(buf, PAGE_SIZE, "Unknown\n"); + } + + /** +@@ -1753,8 +1757,8 @@ lpfc_used_xri_show(struct device *dev, struct device_attribute *attr, + uint32_t cnt, acnt; + + if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL, NULL, NULL)) +- return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); +- return snprintf(buf, PAGE_SIZE, "Unknown\n"); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); ++ return scnprintf(buf, PAGE_SIZE, "Unknown\n"); + } + + /** +@@ -1781,8 +1785,8 @@ lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr, + uint32_t cnt; + + if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, NULL)) +- return snprintf(buf, PAGE_SIZE, "%d\n", cnt); +- return snprintf(buf, PAGE_SIZE, "Unknown\n"); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", cnt); ++ return scnprintf(buf, PAGE_SIZE, "Unknown\n"); + } + + /** +@@ -1809,8 +1813,8 @@ lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr, + uint32_t cnt, acnt; + + if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, &acnt)) +- return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); +- return snprintf(buf, PAGE_SIZE, "Unknown\n"); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); ++ return scnprintf(buf, PAGE_SIZE, "Unknown\n"); + } + + /** +@@ -1835,10 +1839,10 @@ lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr, + struct lpfc_hba *phba = vport->phba; + + if (!(phba->max_vpi)) +- return snprintf(buf, PAGE_SIZE, "NPIV Not Supported\n"); ++ return scnprintf(buf, PAGE_SIZE, "NPIV Not Supported\n"); + if (vport->port_type == LPFC_PHYSICAL_PORT) +- return snprintf(buf, PAGE_SIZE, "NPIV Physical\n"); +- return snprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi); ++ return scnprintf(buf, PAGE_SIZE, "NPIV Physical\n"); ++ return scnprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi); + } + + /** +@@ -1860,7 +1864,7 @@ lpfc_poll_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll); ++ return scnprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll); + } + + /** +@@ -1964,7 +1968,7 @@ lpfc_fips_level_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_level); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", phba->fips_level); + } + + /** +@@ -1983,7 +1987,7 @@ lpfc_fips_rev_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_spec_rev); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", phba->fips_spec_rev); + } + + /** +@@ -2002,7 +2006,7 @@ lpfc_dss_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "%s - %sOperational\n", ++ return scnprintf(buf, PAGE_SIZE, "%s - %sOperational\n", + (phba->cfg_enable_dss) ? "Enabled" : "Disabled", + (phba->sli3_options & LPFC_SLI3_DSS_ENABLED) ? + "" : "Not "); +@@ -2031,7 +2035,7 @@ lpfc_sriov_hw_max_virtfn_show(struct device *dev, + uint16_t max_nr_virtfn; + + max_nr_virtfn = lpfc_sli_sriov_nr_virtfn_get(phba); +- return snprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn); + } + + static inline bool lpfc_rangecheck(uint val, uint min, uint max) +@@ -2091,7 +2095,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ + struct Scsi_Host *shost = class_to_shost(dev);\ + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ + struct lpfc_hba *phba = vport->phba;\ +- return snprintf(buf, PAGE_SIZE, "%d\n",\ ++ return scnprintf(buf, PAGE_SIZE, "%d\n",\ + phba->cfg_##attr);\ + } + +@@ -2119,7 +2123,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ + struct lpfc_hba *phba = vport->phba;\ + uint val = 0;\ + val = phba->cfg_##attr;\ +- return snprintf(buf, PAGE_SIZE, "%#x\n",\ ++ return scnprintf(buf, PAGE_SIZE, "%#x\n",\ + phba->cfg_##attr);\ + } + +@@ -2255,7 +2259,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ + { \ + struct Scsi_Host *shost = class_to_shost(dev);\ + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ +- return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\ ++ return scnprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\ + } + + /** +@@ -2280,7 +2284,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ + { \ + struct Scsi_Host *shost = class_to_shost(dev);\ + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ +- return snprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\ ++ return scnprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\ + } + + /** +@@ -2551,7 +2555,7 @@ lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr, + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + +- return snprintf(buf, PAGE_SIZE, "0x%llx\n", ++ return scnprintf(buf, PAGE_SIZE, "0x%llx\n", + (unsigned long long)phba->cfg_soft_wwpn); + } + +@@ -2648,7 +2652,7 @@ lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr, + { + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; +- return snprintf(buf, PAGE_SIZE, "0x%llx\n", ++ return scnprintf(buf, PAGE_SIZE, "0x%llx\n", + (unsigned long long)phba->cfg_soft_wwnn); + } + +@@ -2714,7 +2718,7 @@ lpfc_oas_tgt_show(struct device *dev, struct device_attribute *attr, + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + +- return snprintf(buf, PAGE_SIZE, "0x%llx\n", ++ return scnprintf(buf, PAGE_SIZE, "0x%llx\n", + wwn_to_u64(phba->cfg_oas_tgt_wwpn)); + } + +@@ -2782,7 +2786,7 @@ lpfc_oas_priority_show(struct device *dev, struct device_attribute *attr, + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + +- return snprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_priority); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_priority); + } + + /** +@@ -2845,7 +2849,7 @@ lpfc_oas_vpt_show(struct device *dev, struct device_attribute *attr, + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + +- return snprintf(buf, PAGE_SIZE, "0x%llx\n", ++ return scnprintf(buf, PAGE_SIZE, "0x%llx\n", + wwn_to_u64(phba->cfg_oas_vpt_wwpn)); + } + +@@ -2916,7 +2920,7 @@ lpfc_oas_lun_state_show(struct device *dev, struct device_attribute *attr, + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + +- return snprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_state); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_state); + } + + /** +@@ -2980,7 +2984,7 @@ lpfc_oas_lun_status_show(struct device *dev, struct device_attribute *attr, + if (!(phba->cfg_oas_flags & OAS_LUN_VALID)) + return -EFAULT; + +- return snprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_status); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_status); + } + static DEVICE_ATTR(lpfc_xlane_lun_status, S_IRUGO, + lpfc_oas_lun_status_show, NULL); +@@ -3132,7 +3136,7 @@ lpfc_oas_lun_show(struct device *dev, struct device_attribute *attr, + if (oas_lun != NOT_OAS_ENABLED_LUN) + phba->cfg_oas_flags |= OAS_LUN_VALID; + +- len += snprintf(buf + len, PAGE_SIZE-len, "0x%llx", oas_lun); ++ len += scnprintf(buf + len, PAGE_SIZE-len, "0x%llx", oas_lun); + + return len; + } +@@ -3266,7 +3270,7 @@ lpfc_iocb_hw_show(struct device *dev, struct device_attribute *attr, char *buf) + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; + +- return snprintf(buf, PAGE_SIZE, "%d\n", phba->iocb_max); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", phba->iocb_max); + } + + static DEVICE_ATTR(iocb_hw, S_IRUGO, +@@ -3278,7 +3282,7 @@ lpfc_txq_hw_show(struct device *dev, struct device_attribute *attr, char *buf) + struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; + struct lpfc_sli_ring *pring = lpfc_phba_elsring(phba); + +- return snprintf(buf, PAGE_SIZE, "%d\n", ++ return scnprintf(buf, PAGE_SIZE, "%d\n", + pring ? pring->txq_max : 0); + } + +@@ -3292,7 +3296,7 @@ lpfc_txcmplq_hw_show(struct device *dev, struct device_attribute *attr, + struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; + struct lpfc_sli_ring *pring = lpfc_phba_elsring(phba); + +- return snprintf(buf, PAGE_SIZE, "%d\n", ++ return scnprintf(buf, PAGE_SIZE, "%d\n", + pring ? pring->txcmplq_max : 0); + } + +@@ -3328,7 +3332,7 @@ lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr, + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + +- return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_devloss_tmo); ++ return scnprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_devloss_tmo); + } + + /** +@@ -4830,19 +4834,19 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr, + + switch (phba->cfg_fcp_cpu_map) { + case 0: +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "fcp_cpu_map: No mapping (%d)\n", + phba->cfg_fcp_cpu_map); + return len; + case 1: +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "fcp_cpu_map: HBA centric mapping (%d): " + "%d online CPUs\n", + phba->cfg_fcp_cpu_map, + phba->sli4_hba.num_online_cpu); + break; + case 2: +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "fcp_cpu_map: Driver centric mapping (%d): " + "%d online CPUs\n", + phba->cfg_fcp_cpu_map, +@@ -4855,14 +4859,14 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr, + + /* margin should fit in this and the truncated message */ + if (cpup->irq == LPFC_VECTOR_MAP_EMPTY) +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "CPU %02d io_chan %02d " + "physid %d coreid %d\n", + phba->sli4_hba.curr_disp_cpu, + cpup->channel_id, cpup->phys_id, + cpup->core_id); + else +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "CPU %02d io_chan %02d " + "physid %d coreid %d IRQ %d\n", + phba->sli4_hba.curr_disp_cpu, +@@ -4875,7 +4879,7 @@ lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr, + if (phba->sli4_hba.curr_disp_cpu < + phba->sli4_hba.num_present_cpu && + (len >= (PAGE_SIZE - 64))) { +- len += snprintf(buf + len, PAGE_SIZE-len, "more...\n"); ++ len += scnprintf(buf + len, PAGE_SIZE-len, "more...\n"); + break; + } + } +@@ -6296,7 +6300,7 @@ lpfc_show_rport_##field (struct device *dev, \ + { \ + struct fc_rport *rport = transport_class_to_rport(dev); \ + struct lpfc_rport_data *rdata = rport->hostdata; \ +- return snprintf(buf, sz, format_string, \ ++ return scnprintf(buf, sz, format_string, \ + (rdata->target) ? cast rdata->target->field : 0); \ + } + +diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c +index 1cbdc892ff95..1a964e71582f 100644 +--- a/drivers/scsi/lpfc/lpfc_ct.c ++++ b/drivers/scsi/lpfc/lpfc_ct.c +@@ -1220,7 +1220,7 @@ lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol, + * Name object. NPIV is not in play so this integer + * value is sufficient and unique per FC-ID. + */ +- n = snprintf(symbol, size, "%d", vport->phba->brd_no); ++ n = scnprintf(symbol, size, "%d", vport->phba->brd_no); + return n; + } + +@@ -1234,26 +1234,26 @@ lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol, + + lpfc_decode_firmware_rev(vport->phba, fwrev, 0); + +- n = snprintf(symbol, size, "Emulex %s", vport->phba->ModelName); ++ n = scnprintf(symbol, size, "Emulex %s", vport->phba->ModelName); + if (size < n) + return n; + +- n += snprintf(symbol + n, size - n, " FV%s", fwrev); ++ n += scnprintf(symbol + n, size - n, " FV%s", fwrev); + if (size < n) + return n; + +- n += snprintf(symbol + n, size - n, " DV%s.", ++ n += scnprintf(symbol + n, size - n, " DV%s.", + lpfc_release_version); + if (size < n) + return n; + +- n += snprintf(symbol + n, size - n, " HN:%s.", ++ n += scnprintf(symbol + n, size - n, " HN:%s.", + init_utsname()->nodename); + if (size < n) + return n; + + /* Note :- OS name is "Linux" */ +- n += snprintf(symbol + n, size - n, " OS:%s\n", ++ n += scnprintf(symbol + n, size - n, " OS:%s\n", + init_utsname()->sysname); + return n; + } +diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c +index ca6c3982548d..f1951c432766 100644 +--- a/drivers/scsi/lpfc/lpfc_debugfs.c ++++ b/drivers/scsi/lpfc/lpfc_debugfs.c +@@ -170,7 +170,7 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) + snprintf(buffer, + LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n", + dtp->seq_cnt, ms, dtp->fmt); +- len += snprintf(buf+len, size-len, buffer, ++ len += scnprintf(buf+len, size-len, buffer, + dtp->data1, dtp->data2, dtp->data3); + } + for (i = 0; i < index; i++) { +@@ -181,7 +181,7 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) + snprintf(buffer, + LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n", + dtp->seq_cnt, ms, dtp->fmt); +- len += snprintf(buf+len, size-len, buffer, ++ len += scnprintf(buf+len, size-len, buffer, + dtp->data1, dtp->data2, dtp->data3); + } + +@@ -236,7 +236,7 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size) + snprintf(buffer, + LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n", + dtp->seq_cnt, ms, dtp->fmt); +- len += snprintf(buf+len, size-len, buffer, ++ len += scnprintf(buf+len, size-len, buffer, + dtp->data1, dtp->data2, dtp->data3); + } + for (i = 0; i < index; i++) { +@@ -247,7 +247,7 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size) + snprintf(buffer, + LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n", + dtp->seq_cnt, ms, dtp->fmt); +- len += snprintf(buf+len, size-len, buffer, ++ len += scnprintf(buf+len, size-len, buffer, + dtp->data1, dtp->data2, dtp->data3); + } + +@@ -307,7 +307,7 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) + + i = lpfc_debugfs_last_hbq; + +- len += snprintf(buf+len, size-len, "HBQ %d Info\n", i); ++ len += scnprintf(buf+len, size-len, "HBQ %d Info\n", i); + + hbqs = &phba->hbqs[i]; + posted = 0; +@@ -315,21 +315,21 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) + posted++; + + hip = lpfc_hbq_defs[i]; +- len += snprintf(buf+len, size-len, ++ len += scnprintf(buf+len, size-len, + "idx:%d prof:%d rn:%d bufcnt:%d icnt:%d acnt:%d posted %d\n", + hip->hbq_index, hip->profile, hip->rn, + hip->buffer_count, hip->init_count, hip->add_count, posted); + + raw_index = phba->hbq_get[i]; + getidx = le32_to_cpu(raw_index); +- len += snprintf(buf+len, size-len, ++ len += scnprintf(buf+len, size-len, + "entries:%d bufcnt:%d Put:%d nPut:%d localGet:%d hbaGet:%d\n", + hbqs->entry_count, hbqs->buffer_count, hbqs->hbqPutIdx, + hbqs->next_hbqPutIdx, hbqs->local_hbqGetIdx, getidx); + + hbqe = (struct lpfc_hbq_entry *) phba->hbqs[i].hbq_virt; + for (j=0; jentry_count; j++) { +- len += snprintf(buf+len, size-len, ++ len += scnprintf(buf+len, size-len, + "%03d: %08x %04x %05x ", j, + le32_to_cpu(hbqe->bde.addrLow), + le32_to_cpu(hbqe->bde.tus.w), +@@ -341,14 +341,16 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) + low = hbqs->hbqPutIdx - posted; + if (low >= 0) { + if ((j >= hbqs->hbqPutIdx) || (j < low)) { +- len += snprintf(buf+len, size-len, "Unused\n"); ++ len += scnprintf(buf + len, size - len, ++ "Unused\n"); + goto skipit; + } + } + else { + if ((j >= hbqs->hbqPutIdx) && + (j < (hbqs->entry_count+low))) { +- len += snprintf(buf+len, size-len, "Unused\n"); ++ len += scnprintf(buf + len, size - len, ++ "Unused\n"); + goto skipit; + } + } +@@ -358,7 +360,7 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) + hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); + phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff); + if (phys == le32_to_cpu(hbqe->bde.addrLow)) { +- len += snprintf(buf+len, size-len, ++ len += scnprintf(buf+len, size-len, + "Buf%d: %p %06x\n", i, + hbq_buf->dbuf.virt, hbq_buf->tag); + found = 1; +@@ -367,7 +369,7 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) + i++; + } + if (!found) { +- len += snprintf(buf+len, size-len, "No DMAinfo?\n"); ++ len += scnprintf(buf+len, size-len, "No DMAinfo?\n"); + } + skipit: + hbqe++; +@@ -413,7 +415,7 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size) + off = 0; + spin_lock_irq(&phba->hbalock); + +- len += snprintf(buf+len, size-len, "HBA SLIM\n"); ++ len += scnprintf(buf+len, size-len, "HBA SLIM\n"); + lpfc_memcpy_from_slim(buffer, + phba->MBslimaddr + lpfc_debugfs_last_hba_slim_off, 1024); + +@@ -427,7 +429,7 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size) + + i = 1024; + while (i > 0) { +- len += snprintf(buf+len, size-len, ++ len += scnprintf(buf+len, size-len, + "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), + *(ptr+5), *(ptr+6), *(ptr+7)); +@@ -471,11 +473,11 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size) + off = 0; + spin_lock_irq(&phba->hbalock); + +- len += snprintf(buf+len, size-len, "SLIM Mailbox\n"); ++ len += scnprintf(buf+len, size-len, "SLIM Mailbox\n"); + ptr = (uint32_t *)phba->slim2p.virt; + i = sizeof(MAILBOX_t); + while (i > 0) { +- len += snprintf(buf+len, size-len, ++ len += scnprintf(buf+len, size-len, + "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), + *(ptr+5), *(ptr+6), *(ptr+7)); +@@ -484,11 +486,11 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size) + off += (8 * sizeof(uint32_t)); + } + +- len += snprintf(buf+len, size-len, "SLIM PCB\n"); ++ len += scnprintf(buf+len, size-len, "SLIM PCB\n"); + ptr = (uint32_t *)phba->pcb; + i = sizeof(PCB_t); + while (i > 0) { +- len += snprintf(buf+len, size-len, ++ len += scnprintf(buf+len, size-len, + "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), + *(ptr+5), *(ptr+6), *(ptr+7)); +@@ -501,7 +503,7 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size) + for (i = 0; i < 4; i++) { + pgpp = &phba->port_gp[i]; + pring = &psli->sli3_ring[i]; +- len += snprintf(buf+len, size-len, ++ len += scnprintf(buf+len, size-len, + "Ring %d: CMD GetInx:%d " + "(Max:%d Next:%d " + "Local:%d flg:x%x) " +@@ -518,7 +520,7 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size) + word1 = readl(phba->CAregaddr); + word2 = readl(phba->HSregaddr); + word3 = readl(phba->HCregaddr); +- len += snprintf(buf+len, size-len, "HA:%08x CA:%08x HS:%08x " ++ len += scnprintf(buf+len, size-len, "HA:%08x CA:%08x HS:%08x " + "HC:%08x\n", word0, word1, word2, word3); + } + spin_unlock_irq(&phba->hbalock); +@@ -557,12 +559,12 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) + cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE); + outio = 0; + +- len += snprintf(buf+len, size-len, "\nFCP Nodelist Entries ...\n"); ++ len += scnprintf(buf+len, size-len, "\nFCP Nodelist Entries ...\n"); + spin_lock_irq(shost->host_lock); + list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { + iocnt = 0; + if (!cnt) { +- len += snprintf(buf+len, size-len, ++ len += scnprintf(buf+len, size-len, + "Missing Nodelist Entries\n"); + break; + } +@@ -600,62 +602,62 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) + default: + statep = "UNKNOWN"; + } +- len += snprintf(buf+len, size-len, "%s DID:x%06x ", ++ len += scnprintf(buf+len, size-len, "%s DID:x%06x ", + statep, ndlp->nlp_DID); +- len += snprintf(buf+len, size-len, ++ len += scnprintf(buf+len, size-len, + "WWPN x%llx ", + wwn_to_u64(ndlp->nlp_portname.u.wwn)); +- len += snprintf(buf+len, size-len, ++ len += scnprintf(buf+len, size-len, + "WWNN x%llx ", + wwn_to_u64(ndlp->nlp_nodename.u.wwn)); + if (ndlp->nlp_flag & NLP_RPI_REGISTERED) +- len += snprintf(buf+len, size-len, "RPI:%03d ", ++ len += scnprintf(buf+len, size-len, "RPI:%03d ", + ndlp->nlp_rpi); + else +- len += snprintf(buf+len, size-len, "RPI:none "); +- len += snprintf(buf+len, size-len, "flag:x%08x ", ++ len += scnprintf(buf+len, size-len, "RPI:none "); ++ len += scnprintf(buf+len, size-len, "flag:x%08x ", + ndlp->nlp_flag); + if (!ndlp->nlp_type) +- len += snprintf(buf+len, size-len, "UNKNOWN_TYPE "); ++ len += scnprintf(buf+len, size-len, "UNKNOWN_TYPE "); + if (ndlp->nlp_type & NLP_FC_NODE) +- len += snprintf(buf+len, size-len, "FC_NODE "); ++ len += scnprintf(buf+len, size-len, "FC_NODE "); + if (ndlp->nlp_type & NLP_FABRIC) { +- len += snprintf(buf+len, size-len, "FABRIC "); ++ len += scnprintf(buf+len, size-len, "FABRIC "); + iocnt = 0; + } + if (ndlp->nlp_type & NLP_FCP_TARGET) +- len += snprintf(buf+len, size-len, "FCP_TGT sid:%d ", ++ len += scnprintf(buf+len, size-len, "FCP_TGT sid:%d ", + ndlp->nlp_sid); + if (ndlp->nlp_type & NLP_FCP_INITIATOR) +- len += snprintf(buf+len, size-len, "FCP_INITIATOR "); ++ len += scnprintf(buf+len, size-len, "FCP_INITIATOR "); + if (ndlp->nlp_type & NLP_NVME_TARGET) +- len += snprintf(buf + len, ++ len += scnprintf(buf + len, + size - len, "NVME_TGT sid:%d ", + NLP_NO_SID); + if (ndlp->nlp_type & NLP_NVME_INITIATOR) +- len += snprintf(buf + len, ++ len += scnprintf(buf + len, + size - len, "NVME_INITIATOR "); +- len += snprintf(buf+len, size-len, "usgmap:%x ", ++ len += scnprintf(buf+len, size-len, "usgmap:%x ", + ndlp->nlp_usg_map); +- len += snprintf(buf+len, size-len, "refcnt:%x", ++ len += scnprintf(buf+len, size-len, "refcnt:%x", + kref_read(&ndlp->kref)); + if (iocnt) { + i = atomic_read(&ndlp->cmd_pending); +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + " OutIO:x%x Qdepth x%x", + i, ndlp->cmd_qdepth); + outio += i; + } +- len += snprintf(buf+len, size-len, "\n"); ++ len += scnprintf(buf+len, size-len, "\n"); + } + spin_unlock_irq(shost->host_lock); + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "\nOutstanding IO x%x\n", outio); + + if (phba->nvmet_support && phba->targetport && (vport == phba->pport)) { + tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "\nNVME Targetport Entry ...\n"); + + /* Port state is only one of two values for now. */ +@@ -663,18 +665,18 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) + statep = "REGISTERED"; + else + statep = "INIT"; +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "TGT WWNN x%llx WWPN x%llx State %s\n", + wwn_to_u64(vport->fc_nodename.u.wwn), + wwn_to_u64(vport->fc_portname.u.wwn), + statep); +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + " Targetport DID x%06x\n", + phba->targetport->port_id); + goto out_exit; + } + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "\nNVME Lport/Rport Entries ...\n"); + + localport = vport->localport; +@@ -689,11 +691,11 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) + else + statep = "UNKNOWN "; + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "Lport DID x%06x PortState %s\n", + localport->port_id, statep); + +- len += snprintf(buf + len, size - len, "\tRport List:\n"); ++ len += scnprintf(buf + len, size - len, "\tRport List:\n"); + list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { + /* local short-hand pointer. */ + spin_lock(&phba->hbalock); +@@ -720,32 +722,32 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) + } + + /* Tab in to show lport ownership. */ +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "\t%s Port ID:x%06x ", + statep, nrport->port_id); +- len += snprintf(buf + len, size - len, "WWPN x%llx ", ++ len += scnprintf(buf + len, size - len, "WWPN x%llx ", + nrport->port_name); +- len += snprintf(buf + len, size - len, "WWNN x%llx ", ++ len += scnprintf(buf + len, size - len, "WWNN x%llx ", + nrport->node_name); + + /* An NVME rport can have multiple roles. */ + if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR) +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "INITIATOR "); + if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET) +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "TARGET "); + if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY) +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "DISCSRVC "); + if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR | + FC_PORT_ROLE_NVME_TARGET | + FC_PORT_ROLE_NVME_DISCOVERY)) +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "UNKNOWN ROLE x%x", + nrport->port_role); + /* Terminate the string. */ +- len += snprintf(buf + len, size - len, "\n"); ++ len += scnprintf(buf + len, size - len, "\n"); + } + + spin_unlock_irq(shost->host_lock); +@@ -784,35 +786,35 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size) + if (!phba->targetport) + return len; + tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "\nNVME Targetport Statistics\n"); + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "LS: Rcv %08x Drop %08x Abort %08x\n", + atomic_read(&tgtp->rcv_ls_req_in), + atomic_read(&tgtp->rcv_ls_req_drop), + atomic_read(&tgtp->xmt_ls_abort)); + if (atomic_read(&tgtp->rcv_ls_req_in) != + atomic_read(&tgtp->rcv_ls_req_out)) { +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "Rcv LS: in %08x != out %08x\n", + atomic_read(&tgtp->rcv_ls_req_in), + atomic_read(&tgtp->rcv_ls_req_out)); + } + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "LS: Xmt %08x Drop %08x Cmpl %08x\n", + atomic_read(&tgtp->xmt_ls_rsp), + atomic_read(&tgtp->xmt_ls_drop), + atomic_read(&tgtp->xmt_ls_rsp_cmpl)); + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "LS: RSP Abort %08x xb %08x Err %08x\n", + atomic_read(&tgtp->xmt_ls_rsp_aborted), + atomic_read(&tgtp->xmt_ls_rsp_xb_set), + atomic_read(&tgtp->xmt_ls_rsp_error)); + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "FCP: Rcv %08x Defer %08x Release %08x " + "Drop %08x\n", + atomic_read(&tgtp->rcv_fcp_cmd_in), +@@ -822,13 +824,13 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size) + + if (atomic_read(&tgtp->rcv_fcp_cmd_in) != + atomic_read(&tgtp->rcv_fcp_cmd_out)) { +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "Rcv FCP: in %08x != out %08x\n", + atomic_read(&tgtp->rcv_fcp_cmd_in), + atomic_read(&tgtp->rcv_fcp_cmd_out)); + } + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "FCP Rsp: read %08x readrsp %08x " + "write %08x rsp %08x\n", + atomic_read(&tgtp->xmt_fcp_read), +@@ -836,31 +838,31 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size) + atomic_read(&tgtp->xmt_fcp_write), + atomic_read(&tgtp->xmt_fcp_rsp)); + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "FCP Rsp Cmpl: %08x err %08x drop %08x\n", + atomic_read(&tgtp->xmt_fcp_rsp_cmpl), + atomic_read(&tgtp->xmt_fcp_rsp_error), + atomic_read(&tgtp->xmt_fcp_rsp_drop)); + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "FCP Rsp Abort: %08x xb %08x xricqe %08x\n", + atomic_read(&tgtp->xmt_fcp_rsp_aborted), + atomic_read(&tgtp->xmt_fcp_rsp_xb_set), + atomic_read(&tgtp->xmt_fcp_xri_abort_cqe)); + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "ABORT: Xmt %08x Cmpl %08x\n", + atomic_read(&tgtp->xmt_fcp_abort), + atomic_read(&tgtp->xmt_fcp_abort_cmpl)); + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "ABORT: Sol %08x Usol %08x Err %08x Cmpl %08x", + atomic_read(&tgtp->xmt_abort_sol), + atomic_read(&tgtp->xmt_abort_unsol), + atomic_read(&tgtp->xmt_abort_rsp), + atomic_read(&tgtp->xmt_abort_rsp_error)); + +- len += snprintf(buf + len, size - len, "\n"); ++ len += scnprintf(buf + len, size - len, "\n"); + + cnt = 0; + spin_lock(&phba->sli4_hba.abts_nvme_buf_list_lock); +@@ -871,7 +873,7 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size) + } + spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock); + if (cnt) { +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "ABORT: %d ctx entries\n", cnt); + spin_lock(&phba->sli4_hba.abts_nvme_buf_list_lock); + list_for_each_entry_safe(ctxp, next_ctxp, +@@ -879,7 +881,7 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size) + list) { + if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ)) + break; +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "Entry: oxid %x state %x " + "flag %x\n", + ctxp->oxid, ctxp->state, +@@ -893,7 +895,7 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size) + tot += atomic_read(&tgtp->xmt_fcp_release); + tot = atomic_read(&tgtp->rcv_fcp_cmd_in) - tot; + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "IO_CTX: %08x WAIT: cur %08x tot %08x\n" + "CTX Outstanding %08llx\n", + phba->sli4_hba.nvmet_xri_cnt, +@@ -911,10 +913,10 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size) + if (!lport) + return len; + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "\nNVME Lport Statistics\n"); + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "LS: Xmt %016x Cmpl %016x\n", + atomic_read(&lport->fc4NvmeLsRequests), + atomic_read(&lport->fc4NvmeLsCmpls)); +@@ -938,20 +940,20 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size) + if (i >= 32) + continue; + +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "FCP (%d): Rd %016llx Wr %016llx " + "IO %016llx ", + i, data1, data2, data3); +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "Cmpl %016llx OutIO %016llx\n", + tot, ((data1 + data2 + data3) - tot)); + } +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "Total FCP Cmpl %016llx Issue %016llx " + "OutIO %016llx\n", + totin, totout, totout - totin); + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "LS Xmt Err: Abrt %08x Err %08x " + "Cmpl Err: xb %08x Err %08x\n", + atomic_read(&lport->xmt_ls_abort), +@@ -959,7 +961,7 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size) + atomic_read(&lport->cmpl_ls_xb), + atomic_read(&lport->cmpl_ls_err)); + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "FCP Xmt Err: noxri %06x nondlp %06x " + "qdepth %06x wqerr %06x err %06x Abrt %06x\n", + atomic_read(&lport->xmt_fcp_noxri), +@@ -969,7 +971,7 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size) + atomic_read(&lport->xmt_fcp_err), + atomic_read(&lport->xmt_fcp_abort)); + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "FCP Cmpl Err: xb %08x Err %08x\n", + atomic_read(&lport->cmpl_fcp_xb), + atomic_read(&lport->cmpl_fcp_err)); +@@ -1001,58 +1003,58 @@ lpfc_debugfs_nvmektime_data(struct lpfc_vport *vport, char *buf, int size) + + if (phba->nvmet_support == 0) { + /* NVME Initiator */ +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "ktime %s: Total Samples: %lld\n", + (phba->ktime_on ? "Enabled" : "Disabled"), + phba->ktime_data_samples); + if (phba->ktime_data_samples == 0) + return len; + +- len += snprintf( ++ len += scnprintf( + buf + len, PAGE_SIZE - len, + "Segment 1: Last NVME Cmd cmpl " + "done -to- Start of next NVME cnd (in driver)\n"); +- len += snprintf( ++ len += scnprintf( + buf + len, PAGE_SIZE - len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg1_total, + phba->ktime_data_samples), + phba->ktime_seg1_min, + phba->ktime_seg1_max); +- len += snprintf( ++ len += scnprintf( + buf + len, PAGE_SIZE - len, + "Segment 2: Driver start of NVME cmd " + "-to- Firmware WQ doorbell\n"); +- len += snprintf( ++ len += scnprintf( + buf + len, PAGE_SIZE - len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg2_total, + phba->ktime_data_samples), + phba->ktime_seg2_min, + phba->ktime_seg2_max); +- len += snprintf( ++ len += scnprintf( + buf + len, PAGE_SIZE - len, + "Segment 3: Firmware WQ doorbell -to- " + "MSI-X ISR cmpl\n"); +- len += snprintf( ++ len += scnprintf( + buf + len, PAGE_SIZE - len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg3_total, + phba->ktime_data_samples), + phba->ktime_seg3_min, + phba->ktime_seg3_max); +- len += snprintf( ++ len += scnprintf( + buf + len, PAGE_SIZE - len, + "Segment 4: MSI-X ISR cmpl -to- " + "NVME cmpl done\n"); +- len += snprintf( ++ len += scnprintf( + buf + len, PAGE_SIZE - len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg4_total, + phba->ktime_data_samples), + phba->ktime_seg4_min, + phba->ktime_seg4_max); +- len += snprintf( ++ len += scnprintf( + buf + len, PAGE_SIZE - len, + "Total IO avg time: %08lld\n", + div_u64(phba->ktime_seg1_total + +@@ -1064,7 +1066,7 @@ lpfc_debugfs_nvmektime_data(struct lpfc_vport *vport, char *buf, int size) + } + + /* NVME Target */ +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "ktime %s: Total Samples: %lld %lld\n", + (phba->ktime_on ? "Enabled" : "Disabled"), + phba->ktime_data_samples, +@@ -1072,46 +1074,46 @@ lpfc_debugfs_nvmektime_data(struct lpfc_vport *vport, char *buf, int size) + if (phba->ktime_data_samples == 0) + return len; + +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Segment 1: MSI-X ISR Rcv cmd -to- " + "cmd pass to NVME Layer\n"); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg1_total, + phba->ktime_data_samples), + phba->ktime_seg1_min, + phba->ktime_seg1_max); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Segment 2: cmd pass to NVME Layer- " + "-to- Driver rcv cmd OP (action)\n"); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg2_total, + phba->ktime_data_samples), + phba->ktime_seg2_min, + phba->ktime_seg2_max); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Segment 3: Driver rcv cmd OP -to- " + "Firmware WQ doorbell: cmd\n"); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg3_total, + phba->ktime_data_samples), + phba->ktime_seg3_min, + phba->ktime_seg3_max); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Segment 4: Firmware WQ doorbell: cmd " + "-to- MSI-X ISR for cmd cmpl\n"); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg4_total, + phba->ktime_data_samples), + phba->ktime_seg4_min, + phba->ktime_seg4_max); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Segment 5: MSI-X ISR for cmd cmpl " + "-to- NVME layer passed cmd done\n"); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg5_total, + phba->ktime_data_samples), +@@ -1119,10 +1121,10 @@ lpfc_debugfs_nvmektime_data(struct lpfc_vport *vport, char *buf, int size) + phba->ktime_seg5_max); + + if (phba->ktime_status_samples == 0) { +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Total: cmd received by MSI-X ISR " + "-to- cmd completed on wire\n"); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "avg:%08lld min:%08lld " + "max %08lld\n", + div_u64(phba->ktime_seg10_total, +@@ -1132,46 +1134,46 @@ lpfc_debugfs_nvmektime_data(struct lpfc_vport *vport, char *buf, int size) + return len; + } + +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Segment 6: NVME layer passed cmd done " + "-to- Driver rcv rsp status OP\n"); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg6_total, + phba->ktime_status_samples), + phba->ktime_seg6_min, + phba->ktime_seg6_max); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Segment 7: Driver rcv rsp status OP " + "-to- Firmware WQ doorbell: status\n"); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg7_total, + phba->ktime_status_samples), + phba->ktime_seg7_min, + phba->ktime_seg7_max); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Segment 8: Firmware WQ doorbell: status" + " -to- MSI-X ISR for status cmpl\n"); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg8_total, + phba->ktime_status_samples), + phba->ktime_seg8_min, + phba->ktime_seg8_max); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Segment 9: MSI-X ISR for status cmpl " + "-to- NVME layer passed status done\n"); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg9_total, + phba->ktime_status_samples), + phba->ktime_seg9_min, + phba->ktime_seg9_max); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "Total: cmd received by MSI-X ISR -to- " + "cmd completed on wire\n"); +- len += snprintf(buf + len, PAGE_SIZE-len, ++ len += scnprintf(buf + len, PAGE_SIZE-len, + "avg:%08lld min:%08lld max %08lld\n", + div_u64(phba->ktime_seg10_total, + phba->ktime_status_samples), +@@ -1206,7 +1208,7 @@ lpfc_debugfs_nvmeio_trc_data(struct lpfc_hba *phba, char *buf, int size) + (phba->nvmeio_trc_size - 1); + skip = phba->nvmeio_trc_output_idx; + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "%s IO Trace %s: next_idx %d skip %d size %d\n", + (phba->nvmet_support ? "NVME" : "NVMET"), + (state ? "Enabled" : "Disabled"), +@@ -1228,18 +1230,18 @@ lpfc_debugfs_nvmeio_trc_data(struct lpfc_hba *phba, char *buf, int size) + if (!dtp->fmt) + continue; + +- len += snprintf(buf + len, size - len, dtp->fmt, ++ len += scnprintf(buf + len, size - len, dtp->fmt, + dtp->data1, dtp->data2, dtp->data3); + + if (phba->nvmeio_trc_output_idx >= phba->nvmeio_trc_size) { + phba->nvmeio_trc_output_idx = 0; +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "Trace Complete\n"); + goto out; + } + + if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ)) { +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "Trace Continue (%d of %d)\n", + phba->nvmeio_trc_output_idx, + phba->nvmeio_trc_size); +@@ -1257,18 +1259,18 @@ lpfc_debugfs_nvmeio_trc_data(struct lpfc_hba *phba, char *buf, int size) + if (!dtp->fmt) + continue; + +- len += snprintf(buf + len, size - len, dtp->fmt, ++ len += scnprintf(buf + len, size - len, dtp->fmt, + dtp->data1, dtp->data2, dtp->data3); + + if (phba->nvmeio_trc_output_idx >= phba->nvmeio_trc_size) { + phba->nvmeio_trc_output_idx = 0; +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "Trace Complete\n"); + goto out; + } + + if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ)) { +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "Trace Continue (%d of %d)\n", + phba->nvmeio_trc_output_idx, + phba->nvmeio_trc_size); +@@ -1276,7 +1278,7 @@ lpfc_debugfs_nvmeio_trc_data(struct lpfc_hba *phba, char *buf, int size) + } + } + +- len += snprintf(buf + len, size - len, ++ len += scnprintf(buf + len, size - len, + "Trace Done\n"); + out: + return len; +@@ -1308,39 +1310,39 @@ lpfc_debugfs_cpucheck_data(struct lpfc_vport *vport, char *buf, int size) + + if (phba->nvmet_support == 0) { + /* NVME Initiator */ +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "CPUcheck %s\n", + (phba->cpucheck_on & LPFC_CHECK_NVME_IO ? + "Enabled" : "Disabled")); + for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) { + if (i >= LPFC_CHECK_CPU_CNT) + break; +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "%02d: xmit x%08x cmpl x%08x\n", + i, phba->cpucheck_xmt_io[i], + phba->cpucheck_cmpl_io[i]); + tot_xmt += phba->cpucheck_xmt_io[i]; + tot_cmpl += phba->cpucheck_cmpl_io[i]; + } +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "tot:xmit x%08x cmpl x%08x\n", + tot_xmt, tot_cmpl); + return len; + } + + /* NVME Target */ +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "CPUcheck %s ", + (phba->cpucheck_on & LPFC_CHECK_NVMET_IO ? + "IO Enabled - " : "IO Disabled - ")); +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "%s\n", + (phba->cpucheck_on & LPFC_CHECK_NVMET_RCV ? + "Rcv Enabled\n" : "Rcv Disabled\n")); + for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) { + if (i >= LPFC_CHECK_CPU_CNT) + break; +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "%02d: xmit x%08x ccmpl x%08x " + "cmpl x%08x rcv x%08x\n", + i, phba->cpucheck_xmt_io[i], +@@ -1352,7 +1354,7 @@ lpfc_debugfs_cpucheck_data(struct lpfc_vport *vport, char *buf, int size) + tot_cmpl += phba->cpucheck_cmpl_io[i]; + tot_ccmpl += phba->cpucheck_ccmpl_io[i]; + } +- len += snprintf(buf + len, PAGE_SIZE - len, ++ len += scnprintf(buf + len, PAGE_SIZE - len, + "tot:xmit x%08x ccmpl x%08x cmpl x%08x rcv x%08x\n", + tot_xmt, tot_ccmpl, tot_cmpl, tot_rcv); + return len; +@@ -1797,28 +1799,29 @@ lpfc_debugfs_dif_err_read(struct file *file, char __user *buf, + int cnt = 0; + + if (dent == phba->debug_writeGuard) +- cnt = snprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wgrd_cnt); ++ cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wgrd_cnt); + else if (dent == phba->debug_writeApp) +- cnt = snprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wapp_cnt); ++ cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wapp_cnt); + else if (dent == phba->debug_writeRef) +- cnt = snprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wref_cnt); ++ cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wref_cnt); + else if (dent == phba->debug_readGuard) +- cnt = snprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rgrd_cnt); ++ cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rgrd_cnt); + else if (dent == phba->debug_readApp) +- cnt = snprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rapp_cnt); ++ cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rapp_cnt); + else if (dent == phba->debug_readRef) +- cnt = snprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rref_cnt); ++ cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rref_cnt); + else if (dent == phba->debug_InjErrNPortID) +- cnt = snprintf(cbuf, 32, "0x%06x\n", phba->lpfc_injerr_nportid); ++ cnt = scnprintf(cbuf, 32, "0x%06x\n", ++ phba->lpfc_injerr_nportid); + else if (dent == phba->debug_InjErrWWPN) { + memcpy(&tmp, &phba->lpfc_injerr_wwpn, sizeof(struct lpfc_name)); + tmp = cpu_to_be64(tmp); +- cnt = snprintf(cbuf, 32, "0x%016llx\n", tmp); ++ cnt = scnprintf(cbuf, 32, "0x%016llx\n", tmp); + } else if (dent == phba->debug_InjErrLBA) { + if (phba->lpfc_injerr_lba == (sector_t)(-1)) +- cnt = snprintf(cbuf, 32, "off\n"); ++ cnt = scnprintf(cbuf, 32, "off\n"); + else +- cnt = snprintf(cbuf, 32, "0x%llx\n", ++ cnt = scnprintf(cbuf, 32, "0x%llx\n", + (uint64_t) phba->lpfc_injerr_lba); + } else + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +@@ -2624,17 +2627,17 @@ lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes, + switch (count) { + case SIZE_U8: /* byte (8 bits) */ + pci_read_config_byte(pdev, where, &u8val); +- len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, + "%03x: %02x\n", where, u8val); + break; + case SIZE_U16: /* word (16 bits) */ + pci_read_config_word(pdev, where, &u16val); +- len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, + "%03x: %04x\n", where, u16val); + break; + case SIZE_U32: /* double word (32 bits) */ + pci_read_config_dword(pdev, where, &u32val); +- len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, + "%03x: %08x\n", where, u32val); + break; + case LPFC_PCI_CFG_BROWSE: /* browse all */ +@@ -2654,25 +2657,25 @@ pcicfg_browse: + offset = offset_label; + + /* Read PCI config space */ +- len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, + "%03x: ", offset_label); + while (index > 0) { + pci_read_config_dword(pdev, offset, &u32val); +- len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, + "%08x ", u32val); + offset += sizeof(uint32_t); + if (offset >= LPFC_PCI_CFG_SIZE) { +- len += snprintf(pbuffer+len, ++ len += scnprintf(pbuffer+len, + LPFC_PCI_CFG_SIZE-len, "\n"); + break; + } + index -= sizeof(uint32_t); + if (!index) +- len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, + "\n"); + else if (!(index % (8 * sizeof(uint32_t)))) { + offset_label += (8 * sizeof(uint32_t)); +- len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, + "\n%03x: ", offset_label); + } + } +@@ -2943,7 +2946,7 @@ lpfc_idiag_baracc_read(struct file *file, char __user *buf, size_t nbytes, + if (acc_range == SINGLE_WORD) { + offset_run = offset; + u32val = readl(mem_mapped_bar + offset_run); +- len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len, + "%05x: %08x\n", offset_run, u32val); + } else + goto baracc_browse; +@@ -2957,35 +2960,35 @@ baracc_browse: + offset_run = offset_label; + + /* Read PCI bar memory mapped space */ +- len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len, + "%05x: ", offset_label); + index = LPFC_PCI_BAR_RD_SIZE; + while (index > 0) { + u32val = readl(mem_mapped_bar + offset_run); +- len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len, + "%08x ", u32val); + offset_run += sizeof(uint32_t); + if (acc_range == LPFC_PCI_BAR_BROWSE) { + if (offset_run >= bar_size) { +- len += snprintf(pbuffer+len, ++ len += scnprintf(pbuffer+len, + LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n"); + break; + } + } else { + if (offset_run >= offset + + (acc_range * sizeof(uint32_t))) { +- len += snprintf(pbuffer+len, ++ len += scnprintf(pbuffer+len, + LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n"); + break; + } + } + index -= sizeof(uint32_t); + if (!index) +- len += snprintf(pbuffer+len, ++ len += scnprintf(pbuffer+len, + LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n"); + else if (!(index % (8 * sizeof(uint32_t)))) { + offset_label += (8 * sizeof(uint32_t)); +- len += snprintf(pbuffer+len, ++ len += scnprintf(pbuffer+len, + LPFC_PCI_BAR_RD_BUF_SIZE-len, + "\n%05x: ", offset_label); + } +@@ -3158,19 +3161,19 @@ __lpfc_idiag_print_wq(struct lpfc_queue *qp, char *wqtype, + if (!qp) + return len; + +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "\t\t%s WQ info: ", wqtype); +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "AssocCQID[%04d]: WQ-STAT[oflow:x%x posted:x%llx]\n", + qp->assoc_qid, qp->q_cnt_1, + (unsigned long long)qp->q_cnt_4); +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "\t\tWQID[%02d], QE-CNT[%04d], QE-SZ[%04d], " + "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]", + qp->queue_id, qp->entry_count, + qp->entry_size, qp->host_index, + qp->hba_index, qp->entry_repost); +- len += snprintf(pbuffer + len, ++ len += scnprintf(pbuffer + len, + LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n"); + return len; + } +@@ -3208,21 +3211,21 @@ __lpfc_idiag_print_cq(struct lpfc_queue *qp, char *cqtype, + if (!qp) + return len; + +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "\t%s CQ info: ", cqtype); +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "AssocEQID[%02d]: CQ STAT[max:x%x relw:x%x " + "xabt:x%x wq:x%llx]\n", + qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2, + qp->q_cnt_3, (unsigned long long)qp->q_cnt_4); +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "\tCQID[%02d], QE-CNT[%04d], QE-SZ[%04d], " + "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]", + qp->queue_id, qp->entry_count, + qp->entry_size, qp->host_index, + qp->hba_index, qp->entry_repost); + +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n"); ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n"); + + return len; + } +@@ -3234,19 +3237,19 @@ __lpfc_idiag_print_rqpair(struct lpfc_queue *qp, struct lpfc_queue *datqp, + if (!qp || !datqp) + return len; + +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "\t\t%s RQ info: ", rqtype); +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "AssocCQID[%02d]: RQ-STAT[nopost:x%x nobuf:x%x " + "posted:x%x rcv:x%llx]\n", + qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2, + qp->q_cnt_3, (unsigned long long)qp->q_cnt_4); +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "\t\tHQID[%02d], QE-CNT[%04d], QE-SZ[%04d], " + "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]\n", + qp->queue_id, qp->entry_count, qp->entry_size, + qp->host_index, qp->hba_index, qp->entry_repost); +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "\t\tDQID[%02d], QE-CNT[%04d], QE-SZ[%04d], " + "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]\n", + datqp->queue_id, datqp->entry_count, +@@ -3331,17 +3334,17 @@ __lpfc_idiag_print_eq(struct lpfc_queue *qp, char *eqtype, + if (!qp) + return len; + +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "\n%s EQ info: EQ-STAT[max:x%x noE:x%x " + "cqe_proc:x%x eqe_proc:x%llx eqd %d]\n", + eqtype, qp->q_cnt_1, qp->q_cnt_2, qp->q_cnt_3, + (unsigned long long)qp->q_cnt_4, qp->q_mode); +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "EQID[%02d], QE-CNT[%04d], QE-SZ[%04d], " + "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]", + qp->queue_id, qp->entry_count, qp->entry_size, + qp->host_index, qp->hba_index, qp->entry_repost); +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n"); ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n"); + + return len; + } +@@ -3399,7 +3402,7 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, + if (phba->cfg_fof == 0) + phba->lpfc_idiag_last_eq = 0; + +- len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, + "EQ %d out of %d HBA EQs\n", + x, phba->io_channel_irqs); + +@@ -3512,7 +3515,7 @@ fof: + return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); + + too_big: +- len += snprintf(pbuffer + len, ++ len += scnprintf(pbuffer + len, + LPFC_QUE_INFO_GET_BUF_SIZE - len, "Truncated ...\n"); + out: + spin_unlock_irq(&phba->hbalock); +@@ -3568,22 +3571,22 @@ lpfc_idiag_queacc_read_qe(char *pbuffer, int len, struct lpfc_queue *pque, + return 0; + + esize = pque->entry_size; +- len += snprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, + "QE-INDEX[%04d]:\n", index); + + offset = 0; + pentry = pque->qe[index].address; + while (esize > 0) { +- len += snprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, + "%08x ", *pentry); + pentry++; + offset += sizeof(uint32_t); + esize -= sizeof(uint32_t); + if (esize > 0 && !(offset % (4 * sizeof(uint32_t)))) +- len += snprintf(pbuffer+len, ++ len += scnprintf(pbuffer+len, + LPFC_QUE_ACC_BUF_SIZE-len, "\n"); + } +- len += snprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, "\n"); ++ len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, "\n"); + + return len; + } +@@ -3989,27 +3992,27 @@ lpfc_idiag_drbacc_read_reg(struct lpfc_hba *phba, char *pbuffer, + + switch (drbregid) { + case LPFC_DRB_EQ: +- len += snprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE-len, + "EQ-DRB-REG: 0x%08x\n", + readl(phba->sli4_hba.EQDBregaddr)); + break; + case LPFC_DRB_CQ: +- len += snprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE - len, ++ len += scnprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE - len, + "CQ-DRB-REG: 0x%08x\n", + readl(phba->sli4_hba.CQDBregaddr)); + break; + case LPFC_DRB_MQ: +- len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, + "MQ-DRB-REG: 0x%08x\n", + readl(phba->sli4_hba.MQDBregaddr)); + break; + case LPFC_DRB_WQ: +- len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, + "WQ-DRB-REG: 0x%08x\n", + readl(phba->sli4_hba.WQDBregaddr)); + break; + case LPFC_DRB_RQ: +- len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, + "RQ-DRB-REG: 0x%08x\n", + readl(phba->sli4_hba.RQDBregaddr)); + break; +@@ -4199,37 +4202,37 @@ lpfc_idiag_ctlacc_read_reg(struct lpfc_hba *phba, char *pbuffer, + + switch (ctlregid) { + case LPFC_CTL_PORT_SEM: +- len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, + "Port SemReg: 0x%08x\n", + readl(phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PORT_SEM_OFFSET)); + break; + case LPFC_CTL_PORT_STA: +- len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, + "Port StaReg: 0x%08x\n", + readl(phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PORT_STA_OFFSET)); + break; + case LPFC_CTL_PORT_CTL: +- len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, + "Port CtlReg: 0x%08x\n", + readl(phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PORT_CTL_OFFSET)); + break; + case LPFC_CTL_PORT_ER1: +- len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, + "Port Er1Reg: 0x%08x\n", + readl(phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PORT_ER1_OFFSET)); + break; + case LPFC_CTL_PORT_ER2: +- len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, + "Port Er2Reg: 0x%08x\n", + readl(phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PORT_ER2_OFFSET)); + break; + case LPFC_CTL_PDEV_CTL: +- len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, + "PDev CtlReg: 0x%08x\n", + readl(phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PDEV_CTL_OFFSET)); +@@ -4422,13 +4425,13 @@ lpfc_idiag_mbxacc_get_setup(struct lpfc_hba *phba, char *pbuffer) + mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX]; + mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX]; + +- len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, + "mbx_dump_map: 0x%08x\n", mbx_dump_map); +- len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, + "mbx_dump_cnt: %04d\n", mbx_dump_cnt); +- len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, + "mbx_word_cnt: %04d\n", mbx_word_cnt); +- len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, + "mbx_mbox_cmd: 0x%02x\n", mbx_mbox_cmd); + + return len; +@@ -4577,35 +4580,35 @@ lpfc_idiag_extacc_avail_get(struct lpfc_hba *phba, char *pbuffer, int len) + { + uint16_t ext_cnt, ext_size; + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\nAvailable Extents Information:\n"); + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\tPort Available VPI extents: "); + lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VPI, + &ext_cnt, &ext_size); +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "Count %3d, Size %3d\n", ext_cnt, ext_size); + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\tPort Available VFI extents: "); + lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VFI, + &ext_cnt, &ext_size); +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "Count %3d, Size %3d\n", ext_cnt, ext_size); + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\tPort Available RPI extents: "); + lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_RPI, + &ext_cnt, &ext_size); +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "Count %3d, Size %3d\n", ext_cnt, ext_size); + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\tPort Available XRI extents: "); + lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_XRI, + &ext_cnt, &ext_size); +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "Count %3d, Size %3d\n", ext_cnt, ext_size); + + return len; +@@ -4629,55 +4632,55 @@ lpfc_idiag_extacc_alloc_get(struct lpfc_hba *phba, char *pbuffer, int len) + uint16_t ext_cnt, ext_size; + int rc; + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\nAllocated Extents Information:\n"); + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\tHost Allocated VPI extents: "); + rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VPI, + &ext_cnt, &ext_size); + if (!rc) +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "Port %d Extent %3d, Size %3d\n", + phba->brd_no, ext_cnt, ext_size); + else +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "N/A\n"); + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\tHost Allocated VFI extents: "); + rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VFI, + &ext_cnt, &ext_size); + if (!rc) +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "Port %d Extent %3d, Size %3d\n", + phba->brd_no, ext_cnt, ext_size); + else +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "N/A\n"); + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\tHost Allocated RPI extents: "); + rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_RPI, + &ext_cnt, &ext_size); + if (!rc) +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "Port %d Extent %3d, Size %3d\n", + phba->brd_no, ext_cnt, ext_size); + else +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "N/A\n"); + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\tHost Allocated XRI extents: "); + rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_XRI, + &ext_cnt, &ext_size); + if (!rc) +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "Port %d Extent %3d, Size %3d\n", + phba->brd_no, ext_cnt, ext_size); + else +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "N/A\n"); + + return len; +@@ -4701,49 +4704,49 @@ lpfc_idiag_extacc_drivr_get(struct lpfc_hba *phba, char *pbuffer, int len) + struct lpfc_rsrc_blks *rsrc_blks; + int index; + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\nDriver Extents Information:\n"); + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\tVPI extents:\n"); + index = 0; + list_for_each_entry(rsrc_blks, &phba->lpfc_vpi_blk_list, list) { +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\t\tBlock %3d: Start %4d, Count %4d\n", + index, rsrc_blks->rsrc_start, + rsrc_blks->rsrc_size); + index++; + } +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\tVFI extents:\n"); + index = 0; + list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_vfi_blk_list, + list) { +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\t\tBlock %3d: Start %4d, Count %4d\n", + index, rsrc_blks->rsrc_start, + rsrc_blks->rsrc_size); + index++; + } + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\tRPI extents:\n"); + index = 0; + list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_rpi_blk_list, + list) { +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\t\tBlock %3d: Start %4d, Count %4d\n", + index, rsrc_blks->rsrc_start, + rsrc_blks->rsrc_size); + index++; + } + +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\tXRI extents:\n"); + index = 0; + list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_xri_blk_list, + list) { +- len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, ++ len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\t\tBlock %3d: Start %4d, Count %4d\n", + index, rsrc_blks->rsrc_start, + rsrc_blks->rsrc_size); +@@ -5137,11 +5140,11 @@ lpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *phba, enum nemb_type nemb_tp, + if (i != 0) + pr_err("%s\n", line_buf); + len = 0; +- len += snprintf(line_buf+len, ++ len += scnprintf(line_buf+len, + LPFC_MBX_ACC_LBUF_SZ-len, + "%03d: ", i); + } +- len += snprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len, ++ len += scnprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len, + "%08x ", (uint32_t)*pword); + pword++; + } +@@ -5204,11 +5207,11 @@ lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *phba, MAILBOX_t *pmbox) + pr_err("%s\n", line_buf); + len = 0; + memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ); +- len += snprintf(line_buf+len, ++ len += scnprintf(line_buf+len, + LPFC_MBX_ACC_LBUF_SZ-len, + "%03d: ", i); + } +- len += snprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len, ++ len += scnprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len, + "%08x ", + ((uint32_t)*pword) & 0xffffffff); + pword++; +@@ -5227,18 +5230,18 @@ lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *phba, MAILBOX_t *pmbox) + pr_err("%s\n", line_buf); + len = 0; + memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ); +- len += snprintf(line_buf+len, ++ len += scnprintf(line_buf+len, + LPFC_MBX_ACC_LBUF_SZ-len, + "%03d: ", i); + } + for (j = 0; j < 4; j++) { +- len += snprintf(line_buf+len, ++ len += scnprintf(line_buf+len, + LPFC_MBX_ACC_LBUF_SZ-len, + "%02x", + ((uint8_t)*pbyte) & 0xff); + pbyte++; + } +- len += snprintf(line_buf+len, ++ len += scnprintf(line_buf+len, + LPFC_MBX_ACC_LBUF_SZ-len, " "); + } + if ((i - 1) % 8) +diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h +index 30efc7bf91bd..824de3e410ca 100644 +--- a/drivers/scsi/lpfc/lpfc_debugfs.h ++++ b/drivers/scsi/lpfc/lpfc_debugfs.h +@@ -342,7 +342,7 @@ lpfc_debug_dump_qe(struct lpfc_queue *q, uint32_t idx) + pword = q->qe[idx].address; + + len = 0; +- len += snprintf(line_buf+len, LPFC_LBUF_SZ-len, "QE[%04d]: ", idx); ++ len += scnprintf(line_buf+len, LPFC_LBUF_SZ-len, "QE[%04d]: ", idx); + if (qe_word_cnt > 8) + printk(KERN_ERR "%s\n", line_buf); + +@@ -353,11 +353,11 @@ lpfc_debug_dump_qe(struct lpfc_queue *q, uint32_t idx) + if (qe_word_cnt > 8) { + len = 0; + memset(line_buf, 0, LPFC_LBUF_SZ); +- len += snprintf(line_buf+len, LPFC_LBUF_SZ-len, ++ len += scnprintf(line_buf+len, LPFC_LBUF_SZ-len, + "%03d: ", i); + } + } +- len += snprintf(line_buf+len, LPFC_LBUF_SZ-len, "%08x ", ++ len += scnprintf(line_buf+len, LPFC_LBUF_SZ-len, "%08x ", + ((uint32_t)*pword) & 0xffffffff); + pword++; + } +diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c +index 4888b999e82f..f8f4d3ea67f3 100644 +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -345,7 +345,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, + } + + ha->optrom_region_start = start; +- ha->optrom_region_size = start + size; ++ ha->optrom_region_size = size; + + ha->optrom_state = QLA_SREADING; + ha->optrom_buffer = vmalloc(ha->optrom_region_size); +@@ -418,7 +418,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, + } + + ha->optrom_region_start = start; +- ha->optrom_region_size = start + size; ++ ha->optrom_region_size = size; + + ha->optrom_state = QLA_SWRITING; + ha->optrom_buffer = vmalloc(ha->optrom_region_size); +diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c +index d2888b30a8a3..a8c67cd17625 100644 +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -981,6 +981,8 @@ void qlt_free_session_done(struct work_struct *work) + sess->send_els_logo); + + if (!IS_SW_RESV_ADDR(sess->d_id)) { ++ qla2x00_mark_device_lost(vha, sess, 0, 0); ++ + if (sess->send_els_logo) { + qlt_port_logo_t logo; + +@@ -1161,8 +1163,6 @@ void qlt_unreg_sess(struct fc_port *sess) + if (sess->se_sess) + vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess); + +- qla2x00_mark_device_lost(vha, sess, 0, 0); +- + sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; + sess->disc_state = DSC_DELETE_PEND; + sess->last_rscn_gen = sess->rscn_gen; +diff --git a/drivers/soc/sunxi/Kconfig b/drivers/soc/sunxi/Kconfig +index 353b07e40176..e84eb4e59f58 100644 +--- a/drivers/soc/sunxi/Kconfig ++++ b/drivers/soc/sunxi/Kconfig +@@ -4,6 +4,7 @@ + config SUNXI_SRAM + bool + default ARCH_SUNXI ++ select REGMAP_MMIO + help + Say y here to enable the SRAM controller support. This + device is responsible on mapping the SRAM in the sunXi SoCs +diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c +index 0529e5628c24..ae5c0285a942 100644 +--- a/drivers/staging/greybus/power_supply.c ++++ b/drivers/staging/greybus/power_supply.c +@@ -520,7 +520,7 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy) + + op = gb_operation_create(connection, + GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS, +- sizeof(req), sizeof(*resp) + props_count * ++ sizeof(*req), sizeof(*resp) + props_count * + sizeof(struct gb_power_supply_props_desc), + GFP_KERNEL); + if (!op) +diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c +index 4569838f27a0..0b48677fa958 100644 +--- a/drivers/staging/most/cdev/cdev.c ++++ b/drivers/staging/most/cdev/cdev.c +@@ -546,7 +546,7 @@ static void __exit mod_exit(void) + destroy_cdev(c); + destroy_channel(c); + } +- unregister_chrdev_region(comp.devno, 1); ++ unregister_chrdev_region(comp.devno, CHRDEV_REGION_SIZE); + ida_destroy(&comp.minor_id); + class_destroy(comp.class); + } +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index 32da5a4182ac..5b442bc68a76 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -470,12 +470,12 @@ static void acm_read_bulk_callback(struct urb *urb) + struct acm *acm = rb->instance; + unsigned long flags; + int status = urb->status; ++ bool stopped = false; ++ bool stalled = false; + + dev_vdbg(&acm->data->dev, "got urb %d, len %d, status %d\n", + rb->index, urb->actual_length, status); + +- set_bit(rb->index, &acm->read_urbs_free); +- + if (!acm->dev) { + dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__); + return; +@@ -488,15 +488,16 @@ static void acm_read_bulk_callback(struct urb *urb) + break; + case -EPIPE: + set_bit(EVENT_RX_STALL, &acm->flags); +- schedule_work(&acm->work); +- return; ++ stalled = true; ++ break; + case -ENOENT: + case -ECONNRESET: + case -ESHUTDOWN: + dev_dbg(&acm->data->dev, + "%s - urb shutting down with status: %d\n", + __func__, status); +- return; ++ stopped = true; ++ break; + default: + dev_dbg(&acm->data->dev, + "%s - nonzero urb status received: %d\n", +@@ -505,10 +506,24 @@ static void acm_read_bulk_callback(struct urb *urb) + } + + /* +- * Unthrottle may run on another CPU which needs to see events +- * in the same order. Submission has an implict barrier ++ * Make sure URB processing is done before marking as free to avoid ++ * racing with unthrottle() on another CPU. Matches the barriers ++ * implied by the test_and_clear_bit() in acm_submit_read_urb(). + */ + smp_mb__before_atomic(); ++ set_bit(rb->index, &acm->read_urbs_free); ++ /* ++ * Make sure URB is marked as free before checking the throttled flag ++ * to avoid racing with unthrottle() on another CPU. Matches the ++ * smp_mb() in unthrottle(). ++ */ ++ smp_mb__after_atomic(); ++ ++ if (stopped || stalled) { ++ if (stalled) ++ schedule_work(&acm->work); ++ return; ++ } + + /* throttle device if requested by tty */ + spin_lock_irqsave(&acm->read_lock, flags); +@@ -842,6 +857,9 @@ static void acm_tty_unthrottle(struct tty_struct *tty) + acm->throttle_req = 0; + spin_unlock_irq(&acm->read_lock); + ++ /* Matches the smp_mb__after_atomic() in acm_read_bulk_callback(). */ ++ smp_mb(); ++ + if (was_throttled) + acm_submit_read_urbs(acm, GFP_KERNEL); + } +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index fec97465ccac..4d5c7dda8f54 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1214,7 +1214,7 @@ static void dwc3_get_properties(struct dwc3 *dwc) + u8 tx_max_burst_prd; + + /* default to highest possible threshold */ +- lpm_nyet_threshold = 0xff; ++ lpm_nyet_threshold = 0xf; + + /* default to -3.5dB de-emphasis */ + tx_de_emphasis = 1; +diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig +index ad08895e78f9..c3dae7d5cb6e 100644 +--- a/drivers/usb/musb/Kconfig ++++ b/drivers/usb/musb/Kconfig +@@ -66,7 +66,7 @@ config USB_MUSB_SUNXI + depends on NOP_USB_XCEIV + depends on PHY_SUN4I_USB + depends on EXTCON +- depends on GENERIC_PHY ++ select GENERIC_PHY + select SUNXI_SRAM + + config USB_MUSB_DAVINCI +diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c +index 96036f87b1de..087e5f1656f8 100644 +--- a/drivers/usb/serial/f81232.c ++++ b/drivers/usb/serial/f81232.c +@@ -556,9 +556,12 @@ static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port) + + static void f81232_close(struct usb_serial_port *port) + { ++ struct f81232_private *port_priv = usb_get_serial_port_data(port); ++ + f81232_port_disable(port); + usb_serial_generic_close(port); + usb_kill_urb(port->interrupt_in_urb); ++ flush_work(&port_priv->interrupt_work); + } + + static void f81232_dtr_rts(struct usb_serial_port *port, int on) +@@ -652,6 +655,40 @@ static int f81232_port_remove(struct usb_serial_port *port) + return 0; + } + ++static int f81232_suspend(struct usb_serial *serial, pm_message_t message) ++{ ++ struct usb_serial_port *port = serial->port[0]; ++ struct f81232_private *port_priv = usb_get_serial_port_data(port); ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) ++ usb_kill_urb(port->read_urbs[i]); ++ ++ usb_kill_urb(port->interrupt_in_urb); ++ ++ if (port_priv) ++ flush_work(&port_priv->interrupt_work); ++ ++ return 0; ++} ++ ++static int f81232_resume(struct usb_serial *serial) ++{ ++ struct usb_serial_port *port = serial->port[0]; ++ int result; ++ ++ if (tty_port_initialized(&port->port)) { ++ result = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); ++ if (result) { ++ dev_err(&port->dev, "submit interrupt urb failed: %d\n", ++ result); ++ return result; ++ } ++ } ++ ++ return usb_serial_generic_resume(serial); ++} ++ + static struct usb_serial_driver f81232_device = { + .driver = { + .owner = THIS_MODULE, +@@ -675,6 +712,8 @@ static struct usb_serial_driver f81232_device = { + .read_int_callback = f81232_read_int_callback, + .port_probe = f81232_port_probe, + .port_remove = f81232_port_remove, ++ .suspend = f81232_suspend, ++ .resume = f81232_resume, + }; + + static struct usb_serial_driver * const serial_drivers[] = { +diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c +index 101ebac43c87..59d82b45e758 100644 +--- a/drivers/usb/storage/scsiglue.c ++++ b/drivers/usb/storage/scsiglue.c +@@ -65,6 +65,7 @@ static const char* host_info(struct Scsi_Host *host) + static int slave_alloc (struct scsi_device *sdev) + { + struct us_data *us = host_to_us(sdev->host); ++ int maxp; + + /* + * Set the INQUIRY transfer length to 36. We don't use any of +@@ -74,20 +75,17 @@ static int slave_alloc (struct scsi_device *sdev) + sdev->inquiry_len = 36; + + /* +- * USB has unusual DMA-alignment requirements: Although the +- * starting address of each scatter-gather element doesn't matter, +- * the length of each element except the last must be divisible +- * by the Bulk maxpacket value. There's currently no way to +- * express this by block-layer constraints, so we'll cop out +- * and simply require addresses to be aligned at 512-byte +- * boundaries. This is okay since most block I/O involves +- * hardware sectors that are multiples of 512 bytes in length, +- * and since host controllers up through USB 2.0 have maxpacket +- * values no larger than 512. +- * +- * But it doesn't suffice for Wireless USB, where Bulk maxpacket +- * values can be as large as 2048. To make that work properly +- * will require changes to the block layer. ++ * USB has unusual scatter-gather requirements: the length of each ++ * scatterlist element except the last must be divisible by the ++ * Bulk maxpacket value. Fortunately this value is always a ++ * power of 2. Inform the block layer about this requirement. ++ */ ++ maxp = usb_maxpacket(us->pusb_dev, us->recv_bulk_pipe, 0); ++ blk_queue_virt_boundary(sdev->request_queue, maxp - 1); ++ ++ /* ++ * Some host controllers may have alignment requirements. ++ * We'll play it safe by requiring 512-byte alignment always. + */ + blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1)); + +diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c +index 1f7b401c4d04..5b1d09367475 100644 +--- a/drivers/usb/storage/uas.c ++++ b/drivers/usb/storage/uas.c +@@ -796,24 +796,33 @@ static int uas_slave_alloc(struct scsi_device *sdev) + { + struct uas_dev_info *devinfo = + (struct uas_dev_info *)sdev->host->hostdata; ++ int maxp; + + sdev->hostdata = devinfo; + + /* +- * USB has unusual DMA-alignment requirements: Although the +- * starting address of each scatter-gather element doesn't matter, +- * the length of each element except the last must be divisible +- * by the Bulk maxpacket value. There's currently no way to +- * express this by block-layer constraints, so we'll cop out +- * and simply require addresses to be aligned at 512-byte +- * boundaries. This is okay since most block I/O involves +- * hardware sectors that are multiples of 512 bytes in length, +- * and since host controllers up through USB 2.0 have maxpacket +- * values no larger than 512. ++ * We have two requirements here. We must satisfy the requirements ++ * of the physical HC and the demands of the protocol, as we ++ * definitely want no additional memory allocation in this path ++ * ruling out using bounce buffers. + * +- * But it doesn't suffice for Wireless USB, where Bulk maxpacket +- * values can be as large as 2048. To make that work properly +- * will require changes to the block layer. ++ * For a transmission on USB to continue we must never send ++ * a package that is smaller than maxpacket. Hence the length of each ++ * scatterlist element except the last must be divisible by the ++ * Bulk maxpacket value. ++ * If the HC does not ensure that through SG, ++ * the upper layer must do that. We must assume nothing ++ * about the capabilities off the HC, so we use the most ++ * pessimistic requirement. ++ */ ++ ++ maxp = usb_maxpacket(devinfo->udev, devinfo->data_in_pipe, 0); ++ blk_queue_virt_boundary(sdev->request_queue, maxp - 1); ++ ++ /* ++ * The protocol has no requirements on alignment in the strict sense. ++ * Controllers may or may not have alignment restrictions. ++ * As this is not exported, we use an extremely conservative guess. + */ + blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1)); + +diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c +index 465a6f5142cc..45b04bc91f24 100644 +--- a/drivers/virtio/virtio_pci_common.c ++++ b/drivers/virtio/virtio_pci_common.c +@@ -255,9 +255,11 @@ void vp_del_vqs(struct virtio_device *vdev) + for (i = 0; i < vp_dev->msix_used_vectors; ++i) + free_irq(pci_irq_vector(vp_dev->pci_dev, i), vp_dev); + +- for (i = 0; i < vp_dev->msix_vectors; i++) +- if (vp_dev->msix_affinity_masks[i]) +- free_cpumask_var(vp_dev->msix_affinity_masks[i]); ++ if (vp_dev->msix_affinity_masks) { ++ for (i = 0; i < vp_dev->msix_vectors; i++) ++ if (vp_dev->msix_affinity_masks[i]) ++ free_cpumask_var(vp_dev->msix_affinity_masks[i]); ++ } + + if (vp_dev->msix_enabled) { + /* Disable the vector used for configuration */ +diff --git a/include/linux/kernel.h b/include/linux/kernel.h +index d6aac75b51ba..3d83ebb302cf 100644 +--- a/include/linux/kernel.h ++++ b/include/linux/kernel.h +@@ -73,8 +73,8 @@ + + #define u64_to_user_ptr(x) ( \ + { \ +- typecheck(u64, x); \ +- (void __user *)(uintptr_t)x; \ ++ typecheck(u64, (x)); \ ++ (void __user *)(uintptr_t)(x); \ + } \ + ) + +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index 1dfb75057580..cc2d0c3b475b 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -182,6 +182,9 @@ struct adv_info { + + #define HCI_MAX_SHORT_NAME_LENGTH 10 + ++/* Min encryption key size to match with SMP */ ++#define HCI_MIN_ENC_KEY_SIZE 7 ++ + /* Default LE RPA expiry time, 15 minutes */ + #define HCI_DEFAULT_RPA_TIMEOUT (15 * 60) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 87bd96399d1c..171b83ebed4a 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -2007,8 +2007,8 @@ event_sched_out(struct perf_event *event, + event->pmu->del(event, 0); + event->oncpu = -1; + +- if (event->pending_disable) { +- event->pending_disable = 0; ++ if (READ_ONCE(event->pending_disable) >= 0) { ++ WRITE_ONCE(event->pending_disable, -1); + state = PERF_EVENT_STATE_OFF; + } + perf_event_set_state(event, state); +@@ -2196,7 +2196,8 @@ EXPORT_SYMBOL_GPL(perf_event_disable); + + void perf_event_disable_inatomic(struct perf_event *event) + { +- event->pending_disable = 1; ++ WRITE_ONCE(event->pending_disable, smp_processor_id()); ++ /* can fail, see perf_pending_event_disable() */ + irq_work_queue(&event->pending); + } + +@@ -5803,10 +5804,45 @@ void perf_event_wakeup(struct perf_event *event) + } + } + ++static void perf_pending_event_disable(struct perf_event *event) ++{ ++ int cpu = READ_ONCE(event->pending_disable); ++ ++ if (cpu < 0) ++ return; ++ ++ if (cpu == smp_processor_id()) { ++ WRITE_ONCE(event->pending_disable, -1); ++ perf_event_disable_local(event); ++ return; ++ } ++ ++ /* ++ * CPU-A CPU-B ++ * ++ * perf_event_disable_inatomic() ++ * @pending_disable = CPU-A; ++ * irq_work_queue(); ++ * ++ * sched-out ++ * @pending_disable = -1; ++ * ++ * sched-in ++ * perf_event_disable_inatomic() ++ * @pending_disable = CPU-B; ++ * irq_work_queue(); // FAILS ++ * ++ * irq_work_run() ++ * perf_pending_event() ++ * ++ * But the event runs on CPU-B and wants disabling there. ++ */ ++ irq_work_queue_on(&event->pending, cpu); ++} ++ + static void perf_pending_event(struct irq_work *entry) + { +- struct perf_event *event = container_of(entry, +- struct perf_event, pending); ++ struct perf_event *event = container_of(entry, struct perf_event, pending); + int rctx; + + rctx = perf_swevent_get_recursion_context(); +@@ -5815,10 +5851,7 @@ static void perf_pending_event(struct irq_work *entry) + * and we won't recurse 'further'. + */ + +- if (event->pending_disable) { +- event->pending_disable = 0; +- perf_event_disable_local(event); +- } ++ perf_pending_event_disable(event); + + if (event->pending_wakeup) { + event->pending_wakeup = 0; +@@ -9969,6 +10002,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, + + + init_waitqueue_head(&event->waitq); ++ event->pending_disable = -1; + init_irq_work(&event->pending, perf_pending_event); + + mutex_init(&event->mmap_mutex); +diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c +index 474b2ccdbe69..99c7f199f2d4 100644 +--- a/kernel/events/ring_buffer.c ++++ b/kernel/events/ring_buffer.c +@@ -393,7 +393,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle, + * store that will be enabled on successful return + */ + if (!handle->size) { /* A, matches D */ +- event->pending_disable = 1; ++ event->pending_disable = smp_processor_id(); + perf_output_wakeup(handle); + local_set(&rb->aux_nest, 0); + goto err_put; +@@ -471,7 +471,7 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size) + + if (wakeup) { + if (handle->aux_flags & PERF_AUX_FLAG_TRUNCATED) +- handle->event->pending_disable = 1; ++ handle->event->pending_disable = smp_processor_id(); + perf_output_wakeup(handle); + } + +diff --git a/kernel/futex.c b/kernel/futex.c +index 5a26d843a015..afdc5eadce6e 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -1306,13 +1306,15 @@ static int lookup_pi_state(u32 __user *uaddr, u32 uval, + + static int lock_pi_update_atomic(u32 __user *uaddr, u32 uval, u32 newval) + { ++ int err; + u32 uninitialized_var(curval); + + if (unlikely(should_fail_futex(true))) + return -EFAULT; + +- if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))) +- return -EFAULT; ++ err = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval); ++ if (unlikely(err)) ++ return err; + + /* If user space value changed, let the caller retry */ + return curval != uval ? -EAGAIN : 0; +@@ -1498,10 +1500,8 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_ + if (unlikely(should_fail_futex(true))) + ret = -EFAULT; + +- if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) { +- ret = -EFAULT; +- +- } else if (curval != uval) { ++ ret = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval); ++ if (!ret && (curval != uval)) { + /* + * If a unconditional UNLOCK_PI operation (user space did not + * try the TID->0 transition) raced with a waiter setting the +@@ -1696,32 +1696,32 @@ retry_private: + double_lock_hb(hb1, hb2); + op_ret = futex_atomic_op_inuser(op, uaddr2); + if (unlikely(op_ret < 0)) { +- + double_unlock_hb(hb1, hb2); + +-#ifndef CONFIG_MMU +- /* +- * we don't get EFAULT from MMU faults if we don't have an MMU, +- * but we might get them from range checking +- */ +- ret = op_ret; +- goto out_put_keys; +-#endif +- +- if (unlikely(op_ret != -EFAULT)) { ++ if (!IS_ENABLED(CONFIG_MMU) || ++ unlikely(op_ret != -EFAULT && op_ret != -EAGAIN)) { ++ /* ++ * we don't get EFAULT from MMU faults if we don't have ++ * an MMU, but we might get them from range checking ++ */ + ret = op_ret; + goto out_put_keys; + } + +- ret = fault_in_user_writeable(uaddr2); +- if (ret) +- goto out_put_keys; ++ if (op_ret == -EFAULT) { ++ ret = fault_in_user_writeable(uaddr2); ++ if (ret) ++ goto out_put_keys; ++ } + +- if (!(flags & FLAGS_SHARED)) ++ if (!(flags & FLAGS_SHARED)) { ++ cond_resched(); + goto retry_private; ++ } + + put_futex_key(&key2); + put_futex_key(&key1); ++ cond_resched(); + goto retry; + } + +@@ -2346,7 +2346,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + u32 uval, uninitialized_var(curval), newval; + struct task_struct *oldowner, *newowner; + u32 newtid; +- int ret; ++ int ret, err = 0; + + lockdep_assert_held(q->lock_ptr); + +@@ -2417,14 +2417,17 @@ retry: + if (!pi_state->owner) + newtid |= FUTEX_OWNER_DIED; + +- if (get_futex_value_locked(&uval, uaddr)) +- goto handle_fault; ++ err = get_futex_value_locked(&uval, uaddr); ++ if (err) ++ goto handle_err; + + for (;;) { + newval = (uval & FUTEX_OWNER_DIED) | newtid; + +- if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) +- goto handle_fault; ++ err = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval); ++ if (err) ++ goto handle_err; ++ + if (curval == uval) + break; + uval = curval; +@@ -2452,23 +2455,37 @@ retry: + return 0; + + /* +- * To handle the page fault we need to drop the locks here. That gives +- * the other task (either the highest priority waiter itself or the +- * task which stole the rtmutex) the chance to try the fixup of the +- * pi_state. So once we are back from handling the fault we need to +- * check the pi_state after reacquiring the locks and before trying to +- * do another fixup. When the fixup has been done already we simply +- * return. ++ * In order to reschedule or handle a page fault, we need to drop the ++ * locks here. In the case of a fault, this gives the other task ++ * (either the highest priority waiter itself or the task which stole ++ * the rtmutex) the chance to try the fixup of the pi_state. So once we ++ * are back from handling the fault we need to check the pi_state after ++ * reacquiring the locks and before trying to do another fixup. When ++ * the fixup has been done already we simply return. + * + * Note: we hold both hb->lock and pi_mutex->wait_lock. We can safely + * drop hb->lock since the caller owns the hb -> futex_q relation. + * Dropping the pi_mutex->wait_lock requires the state revalidate. + */ +-handle_fault: ++handle_err: + raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); + spin_unlock(q->lock_ptr); + +- ret = fault_in_user_writeable(uaddr); ++ switch (err) { ++ case -EFAULT: ++ ret = fault_in_user_writeable(uaddr); ++ break; ++ ++ case -EAGAIN: ++ cond_resched(); ++ ret = 0; ++ break; ++ ++ default: ++ WARN_ON_ONCE(1); ++ ret = err; ++ break; ++ } + + spin_lock(q->lock_ptr); + raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); +@@ -3037,10 +3054,8 @@ retry: + * A unconditional UNLOCK_PI op raced against a waiter + * setting the FUTEX_WAITERS bit. Try again. + */ +- if (ret == -EAGAIN) { +- put_futex_key(&key); +- goto retry; +- } ++ if (ret == -EAGAIN) ++ goto pi_retry; + /* + * wake_futex_pi has detected invalid state. Tell user + * space. +@@ -3055,9 +3070,19 @@ retry: + * preserve the WAITERS bit not the OWNER_DIED one. We are the + * owner. + */ +- if (cmpxchg_futex_value_locked(&curval, uaddr, uval, 0)) { ++ if ((ret = cmpxchg_futex_value_locked(&curval, uaddr, uval, 0))) { + spin_unlock(&hb->lock); +- goto pi_faulted; ++ switch (ret) { ++ case -EFAULT: ++ goto pi_faulted; ++ ++ case -EAGAIN: ++ goto pi_retry; ++ ++ default: ++ WARN_ON_ONCE(1); ++ goto out_putkey; ++ } + } + + /* +@@ -3071,6 +3096,11 @@ out_putkey: + put_futex_key(&key); + return ret; + ++pi_retry: ++ put_futex_key(&key); ++ cond_resched(); ++ goto retry; ++ + pi_faulted: + put_futex_key(&key); + +@@ -3431,6 +3461,7 @@ err_unlock: + int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi) + { + u32 uval, uninitialized_var(nval), mval; ++ int err; + + /* Futex address must be 32bit aligned */ + if ((((unsigned long)uaddr) % sizeof(*uaddr)) != 0) +@@ -3440,42 +3471,57 @@ retry: + if (get_user(uval, uaddr)) + return -1; + +- if ((uval & FUTEX_TID_MASK) == task_pid_vnr(curr)) { +- /* +- * Ok, this dying thread is truly holding a futex +- * of interest. Set the OWNER_DIED bit atomically +- * via cmpxchg, and if the value had FUTEX_WAITERS +- * set, wake up a waiter (if any). (We have to do a +- * futex_wake() even if OWNER_DIED is already set - +- * to handle the rare but possible case of recursive +- * thread-death.) The rest of the cleanup is done in +- * userspace. +- */ +- mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; +- /* +- * We are not holding a lock here, but we want to have +- * the pagefault_disable/enable() protection because +- * we want to handle the fault gracefully. If the +- * access fails we try to fault in the futex with R/W +- * verification via get_user_pages. get_user() above +- * does not guarantee R/W access. If that fails we +- * give up and leave the futex locked. +- */ +- if (cmpxchg_futex_value_locked(&nval, uaddr, uval, mval)) { ++ if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr)) ++ return 0; ++ ++ /* ++ * Ok, this dying thread is truly holding a futex ++ * of interest. Set the OWNER_DIED bit atomically ++ * via cmpxchg, and if the value had FUTEX_WAITERS ++ * set, wake up a waiter (if any). (We have to do a ++ * futex_wake() even if OWNER_DIED is already set - ++ * to handle the rare but possible case of recursive ++ * thread-death.) The rest of the cleanup is done in ++ * userspace. ++ */ ++ mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; ++ ++ /* ++ * We are not holding a lock here, but we want to have ++ * the pagefault_disable/enable() protection because ++ * we want to handle the fault gracefully. If the ++ * access fails we try to fault in the futex with R/W ++ * verification via get_user_pages. get_user() above ++ * does not guarantee R/W access. If that fails we ++ * give up and leave the futex locked. ++ */ ++ if ((err = cmpxchg_futex_value_locked(&nval, uaddr, uval, mval))) { ++ switch (err) { ++ case -EFAULT: + if (fault_in_user_writeable(uaddr)) + return -1; + goto retry; +- } +- if (nval != uval) ++ ++ case -EAGAIN: ++ cond_resched(); + goto retry; + +- /* +- * Wake robust non-PI futexes here. The wakeup of +- * PI futexes happens in exit_pi_state(): +- */ +- if (!pi && (uval & FUTEX_WAITERS)) +- futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); ++ default: ++ WARN_ON_ONCE(1); ++ return err; ++ } + } ++ ++ if (nval != uval) ++ goto retry; ++ ++ /* ++ * Wake robust non-PI futexes here. The wakeup of ++ * PI futexes happens in exit_pi_state(): ++ */ ++ if (!pi && (uval & FUTEX_WAITERS)) ++ futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); ++ + return 0; + } + +diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c +index 5c0ba5ca5930..cd4f9f3e8345 100644 +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -356,8 +356,10 @@ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify) + desc->affinity_notify = notify; + raw_spin_unlock_irqrestore(&desc->lock, flags); + +- if (old_notify) ++ if (old_notify) { ++ cancel_work_sync(&old_notify->work); + kref_put(&old_notify->kref, old_notify->release); ++ } + + return 0; + } +diff --git a/lib/ubsan.c b/lib/ubsan.c +index e4162f59a81c..1e9e2ab25539 100644 +--- a/lib/ubsan.c ++++ b/lib/ubsan.c +@@ -86,11 +86,13 @@ static bool is_inline_int(struct type_descriptor *type) + return bits <= inline_bits; + } + +-static s_max get_signed_val(struct type_descriptor *type, unsigned long val) ++static s_max get_signed_val(struct type_descriptor *type, void *val) + { + if (is_inline_int(type)) { + unsigned extra_bits = sizeof(s_max)*8 - type_bit_width(type); +- return ((s_max)val) << extra_bits >> extra_bits; ++ unsigned long ulong_val = (unsigned long)val; ++ ++ return ((s_max)ulong_val) << extra_bits >> extra_bits; + } + + if (type_bit_width(type) == 64) +@@ -99,15 +101,15 @@ static s_max get_signed_val(struct type_descriptor *type, unsigned long val) + return *(s_max *)val; + } + +-static bool val_is_negative(struct type_descriptor *type, unsigned long val) ++static bool val_is_negative(struct type_descriptor *type, void *val) + { + return type_is_signed(type) && get_signed_val(type, val) < 0; + } + +-static u_max get_unsigned_val(struct type_descriptor *type, unsigned long val) ++static u_max get_unsigned_val(struct type_descriptor *type, void *val) + { + if (is_inline_int(type)) +- return val; ++ return (unsigned long)val; + + if (type_bit_width(type) == 64) + return *(u64 *)val; +@@ -116,7 +118,7 @@ static u_max get_unsigned_val(struct type_descriptor *type, unsigned long val) + } + + static void val_to_string(char *str, size_t size, struct type_descriptor *type, +- unsigned long value) ++ void *value) + { + if (type_is_int(type)) { + if (type_bit_width(type) == 128) { +@@ -163,8 +165,8 @@ static void ubsan_epilogue(unsigned long *flags) + current->in_ubsan--; + } + +-static void handle_overflow(struct overflow_data *data, unsigned long lhs, +- unsigned long rhs, char op) ++static void handle_overflow(struct overflow_data *data, void *lhs, ++ void *rhs, char op) + { + + struct type_descriptor *type = data->type; +@@ -191,8 +193,7 @@ static void handle_overflow(struct overflow_data *data, unsigned long lhs, + } + + void __ubsan_handle_add_overflow(struct overflow_data *data, +- unsigned long lhs, +- unsigned long rhs) ++ void *lhs, void *rhs) + { + + handle_overflow(data, lhs, rhs, '+'); +@@ -200,23 +201,21 @@ void __ubsan_handle_add_overflow(struct overflow_data *data, + EXPORT_SYMBOL(__ubsan_handle_add_overflow); + + void __ubsan_handle_sub_overflow(struct overflow_data *data, +- unsigned long lhs, +- unsigned long rhs) ++ void *lhs, void *rhs) + { + handle_overflow(data, lhs, rhs, '-'); + } + EXPORT_SYMBOL(__ubsan_handle_sub_overflow); + + void __ubsan_handle_mul_overflow(struct overflow_data *data, +- unsigned long lhs, +- unsigned long rhs) ++ void *lhs, void *rhs) + { + handle_overflow(data, lhs, rhs, '*'); + } + EXPORT_SYMBOL(__ubsan_handle_mul_overflow); + + void __ubsan_handle_negate_overflow(struct overflow_data *data, +- unsigned long old_val) ++ void *old_val) + { + unsigned long flags; + char old_val_str[VALUE_LENGTH]; +@@ -237,8 +236,7 @@ EXPORT_SYMBOL(__ubsan_handle_negate_overflow); + + + void __ubsan_handle_divrem_overflow(struct overflow_data *data, +- unsigned long lhs, +- unsigned long rhs) ++ void *lhs, void *rhs) + { + unsigned long flags; + char rhs_val_str[VALUE_LENGTH]; +@@ -323,7 +321,7 @@ static void ubsan_type_mismatch_common(struct type_mismatch_data_common *data, + } + + void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, +- unsigned long ptr) ++ void *ptr) + { + struct type_mismatch_data_common common_data = { + .location = &data->location, +@@ -332,12 +330,12 @@ void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, + .type_check_kind = data->type_check_kind + }; + +- ubsan_type_mismatch_common(&common_data, ptr); ++ ubsan_type_mismatch_common(&common_data, (unsigned long)ptr); + } + EXPORT_SYMBOL(__ubsan_handle_type_mismatch); + + void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data, +- unsigned long ptr) ++ void *ptr) + { + + struct type_mismatch_data_common common_data = { +@@ -347,12 +345,12 @@ void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data, + .type_check_kind = data->type_check_kind + }; + +- ubsan_type_mismatch_common(&common_data, ptr); ++ ubsan_type_mismatch_common(&common_data, (unsigned long)ptr); + } + EXPORT_SYMBOL(__ubsan_handle_type_mismatch_v1); + + void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data, +- unsigned long bound) ++ void *bound) + { + unsigned long flags; + char bound_str[VALUE_LENGTH]; +@@ -369,8 +367,7 @@ void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data, + } + EXPORT_SYMBOL(__ubsan_handle_vla_bound_not_positive); + +-void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, +- unsigned long index) ++void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, void *index) + { + unsigned long flags; + char index_str[VALUE_LENGTH]; +@@ -388,7 +385,7 @@ void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, + EXPORT_SYMBOL(__ubsan_handle_out_of_bounds); + + void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, +- unsigned long lhs, unsigned long rhs) ++ void *lhs, void *rhs) + { + unsigned long flags; + struct type_descriptor *rhs_type = data->rhs_type; +@@ -439,7 +436,7 @@ void __ubsan_handle_builtin_unreachable(struct unreachable_data *data) + EXPORT_SYMBOL(__ubsan_handle_builtin_unreachable); + + void __ubsan_handle_load_invalid_value(struct invalid_value_data *data, +- unsigned long val) ++ void *val) + { + unsigned long flags; + char val_str[VALUE_LENGTH]; +diff --git a/mm/slab.c b/mm/slab.c +index b8e0ec74330f..018d32496e8d 100644 +--- a/mm/slab.c ++++ b/mm/slab.c +@@ -4305,7 +4305,8 @@ static void show_symbol(struct seq_file *m, unsigned long address) + + static int leaks_show(struct seq_file *m, void *p) + { +- struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list); ++ struct kmem_cache *cachep = list_entry(p, struct kmem_cache, ++ root_caches_node); + struct page *page; + struct kmem_cache_node *n; + const char *name; +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index bd4978ce8c45..3cf0764d5793 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -1276,6 +1276,14 @@ int hci_conn_check_link_mode(struct hci_conn *conn) + !test_bit(HCI_CONN_ENCRYPT, &conn->flags)) + return 0; + ++ /* The minimum encryption key size needs to be enforced by the ++ * host stack before establishing any L2CAP connections. The ++ * specification in theory allows a minimum of 1, but to align ++ * BR/EDR and LE transports, a minimum of 7 is chosen. ++ */ ++ if (conn->enc_key_size < HCI_MIN_ENC_KEY_SIZE) ++ return 0; ++ + return 1; + } + +diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c +index 1eaac01f85de..7f36fa73ffee 100644 +--- a/net/bluetooth/hidp/sock.c ++++ b/net/bluetooth/hidp/sock.c +@@ -76,6 +76,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long + sockfd_put(csock); + return err; + } ++ ca.name[sizeof(ca.name)-1] = 0; + + err = hidp_connection_add(&ca, csock, isock); + if (!err && copy_to_user(argp, &ca, sizeof(ca))) +diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c +index bd6226bde45f..17e0101081ef 100644 +--- a/sound/soc/codecs/cs35l35.c ++++ b/sound/soc/codecs/cs35l35.c +@@ -1634,6 +1634,16 @@ err: + return ret; + } + ++static int cs35l35_i2c_remove(struct i2c_client *i2c_client) ++{ ++ struct cs35l35_private *cs35l35 = i2c_get_clientdata(i2c_client); ++ ++ regulator_bulk_disable(cs35l35->num_supplies, cs35l35->supplies); ++ gpiod_set_value_cansleep(cs35l35->reset_gpio, 0); ++ ++ return 0; ++} ++ + static const struct of_device_id cs35l35_of_match[] = { + {.compatible = "cirrus,cs35l35"}, + {}, +@@ -1654,6 +1664,7 @@ static struct i2c_driver cs35l35_i2c_driver = { + }, + .id_table = cs35l35_id, + .probe = cs35l35_i2c_probe, ++ .remove = cs35l35_i2c_remove, + }; + + module_i2c_driver(cs35l35_i2c_driver); +diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c +index 3c266eeb89bf..007ce9f48e44 100644 +--- a/sound/soc/codecs/cs4270.c ++++ b/sound/soc/codecs/cs4270.c +@@ -642,6 +642,7 @@ static const struct regmap_config cs4270_regmap = { + .reg_defaults = cs4270_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(cs4270_reg_defaults), + .cache_type = REGCACHE_RBTREE, ++ .write_flag_mask = CS4270_I2C_INCR, + + .readable_reg = cs4270_reg_is_readable, + .volatile_reg = cs4270_reg_is_volatile, +diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c +index e5b6769b9797..d5f73c837281 100644 +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -529,73 +529,71 @@ static int hdmi_codec_set_fmt(struct snd_soc_dai *dai, + { + struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); + struct hdmi_codec_daifmt cf = { 0 }; +- int ret = 0; + + dev_dbg(dai->dev, "%s()\n", __func__); + +- if (dai->id == DAI_ID_SPDIF) { +- cf.fmt = HDMI_SPDIF; +- } else { +- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { +- case SND_SOC_DAIFMT_CBM_CFM: +- cf.bit_clk_master = 1; +- cf.frame_clk_master = 1; +- break; +- case SND_SOC_DAIFMT_CBS_CFM: +- cf.frame_clk_master = 1; +- break; +- case SND_SOC_DAIFMT_CBM_CFS: +- cf.bit_clk_master = 1; +- break; +- case SND_SOC_DAIFMT_CBS_CFS: +- break; +- default: +- return -EINVAL; +- } ++ if (dai->id == DAI_ID_SPDIF) ++ return 0; ++ ++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBM_CFM: ++ cf.bit_clk_master = 1; ++ cf.frame_clk_master = 1; ++ break; ++ case SND_SOC_DAIFMT_CBS_CFM: ++ cf.frame_clk_master = 1; ++ break; ++ case SND_SOC_DAIFMT_CBM_CFS: ++ cf.bit_clk_master = 1; ++ break; ++ case SND_SOC_DAIFMT_CBS_CFS: ++ break; ++ default: ++ return -EINVAL; ++ } + +- switch (fmt & SND_SOC_DAIFMT_INV_MASK) { +- case SND_SOC_DAIFMT_NB_NF: +- break; +- case SND_SOC_DAIFMT_NB_IF: +- cf.frame_clk_inv = 1; +- break; +- case SND_SOC_DAIFMT_IB_NF: +- cf.bit_clk_inv = 1; +- break; +- case SND_SOC_DAIFMT_IB_IF: +- cf.frame_clk_inv = 1; +- cf.bit_clk_inv = 1; +- break; +- } ++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { ++ case SND_SOC_DAIFMT_NB_NF: ++ break; ++ case SND_SOC_DAIFMT_NB_IF: ++ cf.frame_clk_inv = 1; ++ break; ++ case SND_SOC_DAIFMT_IB_NF: ++ cf.bit_clk_inv = 1; ++ break; ++ case SND_SOC_DAIFMT_IB_IF: ++ cf.frame_clk_inv = 1; ++ cf.bit_clk_inv = 1; ++ break; ++ } + +- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { +- case SND_SOC_DAIFMT_I2S: +- cf.fmt = HDMI_I2S; +- break; +- case SND_SOC_DAIFMT_DSP_A: +- cf.fmt = HDMI_DSP_A; +- break; +- case SND_SOC_DAIFMT_DSP_B: +- cf.fmt = HDMI_DSP_B; +- break; +- case SND_SOC_DAIFMT_RIGHT_J: +- cf.fmt = HDMI_RIGHT_J; +- break; +- case SND_SOC_DAIFMT_LEFT_J: +- cf.fmt = HDMI_LEFT_J; +- break; +- case SND_SOC_DAIFMT_AC97: +- cf.fmt = HDMI_AC97; +- break; +- default: +- dev_err(dai->dev, "Invalid DAI interface format\n"); +- return -EINVAL; +- } ++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_I2S: ++ cf.fmt = HDMI_I2S; ++ break; ++ case SND_SOC_DAIFMT_DSP_A: ++ cf.fmt = HDMI_DSP_A; ++ break; ++ case SND_SOC_DAIFMT_DSP_B: ++ cf.fmt = HDMI_DSP_B; ++ break; ++ case SND_SOC_DAIFMT_RIGHT_J: ++ cf.fmt = HDMI_RIGHT_J; ++ break; ++ case SND_SOC_DAIFMT_LEFT_J: ++ cf.fmt = HDMI_LEFT_J; ++ break; ++ case SND_SOC_DAIFMT_AC97: ++ cf.fmt = HDMI_AC97; ++ break; ++ default: ++ dev_err(dai->dev, "Invalid DAI interface format\n"); ++ return -EINVAL; + } + + hcp->daifmt[dai->id] = cf; + +- return ret; ++ return 0; + } + + static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute) +@@ -792,8 +790,10 @@ static int hdmi_codec_probe(struct platform_device *pdev) + i++; + } + +- if (hcd->spdif) ++ if (hcd->spdif) { + hcp->daidrv[i] = hdmi_spdif_dai; ++ hcp->daifmt[DAI_ID_SPDIF].fmt = HDMI_SPDIF; ++ } + + dev_set_drvdata(dev, hcp); + +diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c +index bfd74b86c9d2..645aa0794123 100644 +--- a/sound/soc/codecs/nau8810.c ++++ b/sound/soc/codecs/nau8810.c +@@ -411,9 +411,9 @@ static const struct snd_soc_dapm_widget nau8810_dapm_widgets[] = { + SND_SOC_DAPM_MIXER("Mono Mixer", NAU8810_REG_POWER3, + NAU8810_MOUTMX_EN_SFT, 0, &nau8810_mono_mixer_controls[0], + ARRAY_SIZE(nau8810_mono_mixer_controls)), +- SND_SOC_DAPM_DAC("DAC", "HiFi Playback", NAU8810_REG_POWER3, ++ SND_SOC_DAPM_DAC("DAC", "Playback", NAU8810_REG_POWER3, + NAU8810_DAC_EN_SFT, 0), +- SND_SOC_DAPM_ADC("ADC", "HiFi Capture", NAU8810_REG_POWER2, ++ SND_SOC_DAPM_ADC("ADC", "Capture", NAU8810_REG_POWER2, + NAU8810_ADC_EN_SFT, 0), + SND_SOC_DAPM_PGA("SpkN Out", NAU8810_REG_POWER3, + NAU8810_NSPK_EN_SFT, 0, NULL, 0), +diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c +index 468d5143e2c4..663a208c2f78 100644 +--- a/sound/soc/codecs/nau8824.c ++++ b/sound/soc/codecs/nau8824.c +@@ -681,8 +681,8 @@ static const struct snd_soc_dapm_widget nau8824_dapm_widgets[] = { + SND_SOC_DAPM_ADC("ADCR", NULL, NAU8824_REG_ANALOG_ADC_2, + NAU8824_ADCR_EN_SFT, 0), + +- SND_SOC_DAPM_AIF_OUT("AIFTX", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0), +- SND_SOC_DAPM_AIF_IN("AIFRX", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("AIFTX", "Capture", 0, SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_IN("AIFRX", "Playback", 0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_DAC("DACL", NULL, NAU8824_REG_RDAC, + NAU8824_DACL_EN_SFT, 0), +@@ -831,6 +831,36 @@ static void nau8824_int_status_clear_all(struct regmap *regmap) + } + } + ++static void nau8824_dapm_disable_pin(struct nau8824 *nau8824, const char *pin) ++{ ++ struct snd_soc_dapm_context *dapm = nau8824->dapm; ++ const char *prefix = dapm->component->name_prefix; ++ char prefixed_pin[80]; ++ ++ if (prefix) { ++ snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s", ++ prefix, pin); ++ snd_soc_dapm_disable_pin(dapm, prefixed_pin); ++ } else { ++ snd_soc_dapm_disable_pin(dapm, pin); ++ } ++} ++ ++static void nau8824_dapm_enable_pin(struct nau8824 *nau8824, const char *pin) ++{ ++ struct snd_soc_dapm_context *dapm = nau8824->dapm; ++ const char *prefix = dapm->component->name_prefix; ++ char prefixed_pin[80]; ++ ++ if (prefix) { ++ snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s", ++ prefix, pin); ++ snd_soc_dapm_force_enable_pin(dapm, prefixed_pin); ++ } else { ++ snd_soc_dapm_force_enable_pin(dapm, pin); ++ } ++} ++ + static void nau8824_eject_jack(struct nau8824 *nau8824) + { + struct snd_soc_dapm_context *dapm = nau8824->dapm; +@@ -839,8 +869,8 @@ static void nau8824_eject_jack(struct nau8824 *nau8824) + /* Clear all interruption status */ + nau8824_int_status_clear_all(regmap); + +- snd_soc_dapm_disable_pin(dapm, "SAR"); +- snd_soc_dapm_disable_pin(dapm, "MICBIAS"); ++ nau8824_dapm_disable_pin(nau8824, "SAR"); ++ nau8824_dapm_disable_pin(nau8824, "MICBIAS"); + snd_soc_dapm_sync(dapm); + + /* Enable the insertion interruption, disable the ejection +@@ -870,8 +900,8 @@ static void nau8824_jdet_work(struct work_struct *work) + struct regmap *regmap = nau8824->regmap; + int adc_value, event = 0, event_mask = 0; + +- snd_soc_dapm_force_enable_pin(dapm, "MICBIAS"); +- snd_soc_dapm_force_enable_pin(dapm, "SAR"); ++ nau8824_dapm_enable_pin(nau8824, "MICBIAS"); ++ nau8824_dapm_enable_pin(nau8824, "SAR"); + snd_soc_dapm_sync(dapm); + + msleep(100); +@@ -882,8 +912,8 @@ static void nau8824_jdet_work(struct work_struct *work) + if (adc_value < HEADSET_SARADC_THD) { + event |= SND_JACK_HEADPHONE; + +- snd_soc_dapm_disable_pin(dapm, "SAR"); +- snd_soc_dapm_disable_pin(dapm, "MICBIAS"); ++ nau8824_dapm_disable_pin(nau8824, "SAR"); ++ nau8824_dapm_disable_pin(nau8824, "MICBIAS"); + snd_soc_dapm_sync(dapm); + } else { + event |= SND_JACK_HEADSET; +diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c +index 79ebcc239786..6f5dac09cede 100644 +--- a/sound/soc/codecs/rt5682.c ++++ b/sound/soc/codecs/rt5682.c +@@ -1196,7 +1196,7 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w, + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); +- int ref, val, reg, sft, mask, idx = -EINVAL; ++ int ref, val, reg, idx = -EINVAL; + static const int div_f[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48}; + static const int div_o[] = {1, 2, 4, 6, 8, 12, 16, 24, 32, 48}; + +@@ -1210,15 +1210,10 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w, + + idx = rt5682_div_sel(rt5682, ref, div_f, ARRAY_SIZE(div_f)); + +- if (w->shift == RT5682_PWR_ADC_S1F_BIT) { ++ if (w->shift == RT5682_PWR_ADC_S1F_BIT) + reg = RT5682_PLL_TRACK_3; +- sft = RT5682_ADC_OSR_SFT; +- mask = RT5682_ADC_OSR_MASK; +- } else { ++ else + reg = RT5682_PLL_TRACK_2; +- sft = RT5682_DAC_OSR_SFT; +- mask = RT5682_DAC_OSR_MASK; +- } + + snd_soc_component_update_bits(component, reg, + RT5682_FILTER_CLK_DIV_MASK, idx << RT5682_FILTER_CLK_DIV_SFT); +@@ -1230,7 +1225,8 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w, + } + + snd_soc_component_update_bits(component, RT5682_ADDA_CLK_1, +- mask, idx << sft); ++ RT5682_ADC_OSR_MASK | RT5682_DAC_OSR_MASK, ++ (idx << RT5682_ADC_OSR_SFT) | (idx << RT5682_DAC_OSR_SFT)); + + return 0; + } +diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c +index f03195d2ab2e..45d9f4a09044 100644 +--- a/sound/soc/codecs/tlv320aic32x4.c ++++ b/sound/soc/codecs/tlv320aic32x4.c +@@ -462,6 +462,8 @@ static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("IN2_R"), + SND_SOC_DAPM_INPUT("IN3_L"), + SND_SOC_DAPM_INPUT("IN3_R"), ++ SND_SOC_DAPM_INPUT("CM_L"), ++ SND_SOC_DAPM_INPUT("CM_R"), + }; + + static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = { +diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c +index 6a271e6e6b8f..6c0a3dad44b8 100644 +--- a/sound/soc/codecs/tlv320aic3x.c ++++ b/sound/soc/codecs/tlv320aic3x.c +@@ -1599,7 +1599,6 @@ static int aic3x_probe(struct snd_soc_component *component) + struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component); + int ret, i; + +- INIT_LIST_HEAD(&aic3x->list); + aic3x->component = component; + + for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) { +@@ -1682,7 +1681,6 @@ static void aic3x_remove(struct snd_soc_component *component) + struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component); + int i; + +- list_del(&aic3x->list); + for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) + regulator_unregister_notifier(aic3x->supplies[i].consumer, + &aic3x->disable_nb[i].nb); +@@ -1880,6 +1878,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, + if (ret != 0) + goto err_gpio; + ++ INIT_LIST_HEAD(&aic3x->list); + list_add(&aic3x->list, &reset_list); + + return 0; +@@ -1896,6 +1895,8 @@ static int aic3x_i2c_remove(struct i2c_client *client) + { + struct aic3x_priv *aic3x = i2c_get_clientdata(client); + ++ list_del(&aic3x->list); ++ + if (gpio_is_valid(aic3x->gpio_reset) && + !aic3x_is_shared_reset(aic3x)) { + gpio_set_value(aic3x->gpio_reset, 0); +diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c +index a651fed62a27..ee85056a8577 100644 +--- a/sound/soc/codecs/wm_adsp.c ++++ b/sound/soc/codecs/wm_adsp.c +@@ -3819,11 +3819,13 @@ irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp) + struct regmap *regmap = dsp->regmap; + int ret = 0; + ++ mutex_lock(&dsp->pwr_lock); ++ + ret = regmap_read(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, &val); + if (ret) { + adsp_err(dsp, + "Failed to read Region Lock Ctrl register: %d\n", ret); +- return IRQ_HANDLED; ++ goto error; + } + + if (val & ADSP2_WDT_TIMEOUT_STS_MASK) { +@@ -3842,7 +3844,7 @@ irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp) + adsp_err(dsp, + "Failed to read Bus Err Addr register: %d\n", + ret); +- return IRQ_HANDLED; ++ goto error; + } + + adsp_err(dsp, "bus error address = 0x%x\n", +@@ -3855,7 +3857,7 @@ irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp) + adsp_err(dsp, + "Failed to read Pmem Xmem Err Addr register: %d\n", + ret); +- return IRQ_HANDLED; ++ goto error; + } + + adsp_err(dsp, "xmem error address = 0x%x\n", +@@ -3868,6 +3870,9 @@ irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp) + regmap_update_bits(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, + ADSP2_CTRL_ERR_EINT, ADSP2_CTRL_ERR_EINT); + ++error: ++ mutex_unlock(&dsp->pwr_lock); ++ + return IRQ_HANDLED; + } + EXPORT_SYMBOL_GPL(wm_adsp2_bus_error); +diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +index a892b37eab7c..b8a03f58ac8c 100644 +--- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c ++++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +@@ -406,7 +406,7 @@ static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { + }; + + static const unsigned int dmic_2ch[] = { +- 4, ++ 2, + }; + + static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { +diff --git a/sound/soc/intel/common/sst-firmware.c b/sound/soc/intel/common/sst-firmware.c +index 11041aedea31..6cfcc1042989 100644 +--- a/sound/soc/intel/common/sst-firmware.c ++++ b/sound/soc/intel/common/sst-firmware.c +@@ -1251,11 +1251,15 @@ struct sst_dsp *sst_dsp_new(struct device *dev, + goto irq_err; + + err = sst_dma_new(sst); +- if (err) +- dev_warn(dev, "sst_dma_new failed %d\n", err); ++ if (err) { ++ dev_err(dev, "sst_dma_new failed %d\n", err); ++ goto dma_err; ++ } + + return sst; + ++dma_err: ++ free_irq(sst->irq, sst); + irq_err: + if (sst->ops->free) + sst->ops->free(sst); +diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c +index 823e39103edd..6b2c8c6e7a00 100644 +--- a/sound/soc/intel/skylake/skl-pcm.c ++++ b/sound/soc/intel/skylake/skl-pcm.c +@@ -180,6 +180,7 @@ int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params) + struct hdac_stream *hstream; + struct hdac_ext_stream *stream; + struct hdac_ext_link *link; ++ unsigned char stream_tag; + + hstream = snd_hdac_get_stream(bus, params->stream, + params->link_dma_id + 1); +@@ -198,10 +199,13 @@ int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params) + + snd_hdac_ext_link_stream_setup(stream, format_val); + +- list_for_each_entry(link, &bus->hlink_list, list) { +- if (link->index == params->link_index) +- snd_hdac_ext_link_set_stream_id(link, +- hstream->stream_tag); ++ stream_tag = hstream->stream_tag; ++ if (stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) { ++ list_for_each_entry(link, &bus->hlink_list, list) { ++ if (link->index == params->link_index) ++ snd_hdac_ext_link_set_stream_id(link, ++ stream_tag); ++ } + } + + stream->link_prepared = 1; +@@ -640,6 +644,7 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream, + struct hdac_ext_stream *link_dev = + snd_soc_dai_get_dma_data(dai, substream); + struct hdac_ext_link *link; ++ unsigned char stream_tag; + + dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); + +@@ -649,7 +654,11 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream, + if (!link) + return -EINVAL; + +- snd_hdac_ext_link_clear_stream_id(link, hdac_stream(link_dev)->stream_tag); ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ stream_tag = hdac_stream(link_dev)->stream_tag; ++ snd_hdac_ext_link_clear_stream_id(link, stream_tag); ++ } ++ + snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK); + return 0; + } +diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c +index 400e29edb1c9..8a2e3bbce3a1 100644 +--- a/sound/soc/rockchip/rockchip_pdm.c ++++ b/sound/soc/rockchip/rockchip_pdm.c +@@ -208,7 +208,9 @@ static int rockchip_pdm_set_fmt(struct snd_soc_dai *cpu_dai, + return -EINVAL; + } + ++ pm_runtime_get_sync(cpu_dai->dev); + regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, mask, val); ++ pm_runtime_put(cpu_dai->dev); + + return 0; + } +diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c +index e7b371b07230..45c6d7396785 100644 +--- a/sound/soc/samsung/odroid.c ++++ b/sound/soc/samsung/odroid.c +@@ -64,11 +64,11 @@ static int odroid_card_hw_params(struct snd_pcm_substream *substream, + return ret; + + /* +- * We add 1 to the rclk_freq value in order to avoid too low clock ++ * We add 2 to the rclk_freq value in order to avoid too low clock + * frequency values due to the EPLL output frequency not being exact + * multiple of the audio sampling rate. + */ +- rclk_freq = params_rate(params) * rfs + 1; ++ rclk_freq = params_rate(params) * rfs + 2; + + ret = clk_set_rate(priv->sclk_i2s, rclk_freq); + if (ret < 0) +diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c +index 9b78fb3daa7b..2257b1b0151c 100644 +--- a/sound/soc/soc-dapm.c ++++ b/sound/soc/soc-dapm.c +@@ -3847,6 +3847,10 @@ snd_soc_dapm_free_kcontrol(struct snd_soc_card *card, + int count; + + devm_kfree(card->dev, (void *)*private_value); ++ ++ if (!w_param_text) ++ return; ++ + for (count = 0 ; count < num_params; count++) + devm_kfree(card->dev, (void *)w_param_text[count]); + devm_kfree(card->dev, w_param_text); +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index e8b98bfd4cf1..33060af18b5a 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -957,10 +957,13 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, + codec_params = *params; + + /* fixup params based on TDM slot masks */ +- if (codec_dai->tx_mask) ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && ++ codec_dai->tx_mask) + soc_pcm_codec_params_fixup(&codec_params, + codec_dai->tx_mask); +- if (codec_dai->rx_mask) ++ ++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && ++ codec_dai->rx_mask) + soc_pcm_codec_params_fixup(&codec_params, + codec_dai->rx_mask); + +diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c +index 706ff005234f..24948b95eb19 100644 +--- a/sound/soc/stm/stm32_adfsdm.c ++++ b/sound/soc/stm/stm32_adfsdm.c +@@ -9,6 +9,7 @@ + + #include + #include ++#include + #include + #include + +@@ -37,6 +38,8 @@ struct stm32_adfsdm_priv { + /* PCM buffer */ + unsigned char *pcm_buff; + unsigned int pos; ++ ++ struct mutex lock; /* protect against race condition on iio state */ + }; + + static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = { +@@ -62,10 +65,12 @@ static void stm32_adfsdm_shutdown(struct snd_pcm_substream *substream, + { + struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai); + ++ mutex_lock(&priv->lock); + if (priv->iio_active) { + iio_channel_stop_all_cb(priv->iio_cb); + priv->iio_active = false; + } ++ mutex_unlock(&priv->lock); + } + + static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream, +@@ -74,13 +79,19 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream, + struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai); + int ret; + ++ mutex_lock(&priv->lock); ++ if (priv->iio_active) { ++ iio_channel_stop_all_cb(priv->iio_cb); ++ priv->iio_active = false; ++ } ++ + ret = iio_write_channel_attribute(priv->iio_ch, + substream->runtime->rate, 0, + IIO_CHAN_INFO_SAMP_FREQ); + if (ret < 0) { + dev_err(dai->dev, "%s: Failed to set %d sampling rate\n", + __func__, substream->runtime->rate); +- return ret; ++ goto out; + } + + if (!priv->iio_active) { +@@ -92,6 +103,9 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream, + __func__, ret); + } + ++out: ++ mutex_unlock(&priv->lock); ++ + return ret; + } + +@@ -290,6 +304,7 @@ MODULE_DEVICE_TABLE(of, stm32_adfsdm_of_match); + static int stm32_adfsdm_probe(struct platform_device *pdev) + { + struct stm32_adfsdm_priv *priv; ++ struct snd_soc_component *component; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +@@ -298,6 +313,7 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) + + priv->dev = &pdev->dev; + priv->dai_drv = stm32_adfsdm_dai; ++ mutex_init(&priv->lock); + + dev_set_drvdata(&pdev->dev, priv); + +@@ -316,9 +332,15 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) + if (IS_ERR(priv->iio_cb)) + return PTR_ERR(priv->iio_cb); + +- ret = devm_snd_soc_register_component(&pdev->dev, +- &stm32_adfsdm_soc_platform, +- NULL, 0); ++ component = devm_kzalloc(&pdev->dev, sizeof(*component), GFP_KERNEL); ++ if (!component) ++ return -ENOMEM; ++#ifdef CONFIG_DEBUG_FS ++ component->debugfs_prefix = "pcm"; ++#endif ++ ++ ret = snd_soc_add_component(&pdev->dev, component, ++ &stm32_adfsdm_soc_platform, NULL, 0); + if (ret < 0) + dev_err(&pdev->dev, "%s: Failed to register PCM platform\n", + __func__); +@@ -326,12 +348,20 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) + return ret; + } + ++static int stm32_adfsdm_remove(struct platform_device *pdev) ++{ ++ snd_soc_unregister_component(&pdev->dev); ++ ++ return 0; ++} ++ + static struct platform_driver stm32_adfsdm_driver = { + .driver = { + .name = STM32_ADFSDM_DRV_NAME, + .of_match_table = stm32_adfsdm_of_match, + }, + .probe = stm32_adfsdm_probe, ++ .remove = stm32_adfsdm_remove, + }; + + module_platform_driver(stm32_adfsdm_driver); +diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c +index 85c4b6d8e89d..2fb2b914e78b 100644 +--- a/sound/soc/stm/stm32_sai_sub.c ++++ b/sound/soc/stm/stm32_sai_sub.c +@@ -96,7 +96,7 @@ + * @slot_mask: rx or tx active slots mask. set at init or at runtime + * @data_size: PCM data width. corresponds to PCM substream width. + * @spdif_frm_cnt: S/PDIF playback frame counter +- * @snd_aes_iec958: iec958 data ++ * @iec958: iec958 data + * @ctrl_lock: control lock + */ + struct stm32_sai_sub_data { +@@ -498,6 +498,14 @@ static int stm32_sai_startup(struct snd_pcm_substream *substream, + + sai->substream = substream; + ++ if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { ++ snd_pcm_hw_constraint_mask64(substream->runtime, ++ SNDRV_PCM_HW_PARAM_FORMAT, ++ SNDRV_PCM_FMTBIT_S32_LE); ++ snd_pcm_hw_constraint_single(substream->runtime, ++ SNDRV_PCM_HW_PARAM_CHANNELS, 2); ++ } ++ + ret = clk_prepare_enable(sai->sai_ck); + if (ret < 0) { + dev_err(cpu_dai->dev, "Failed to enable clock: %d\n", ret); +@@ -888,11 +896,12 @@ static int stm32_sai_pcm_new(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *cpu_dai) + { + struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); ++ struct snd_kcontrol_new knew = iec958_ctls; + + if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { + dev_dbg(&sai->pdev->dev, "%s: register iec controls", __func__); +- return snd_ctl_add(rtd->pcm->card, +- snd_ctl_new1(&iec958_ctls, sai)); ++ knew.device = rtd->pcm->device; ++ return snd_ctl_add(rtd->pcm->card, snd_ctl_new1(&knew, sai)); + } + + return 0; +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 550f17611bd7..ef152daccc33 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -165,6 +165,7 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func, + "fortify_panic", + "usercopy_abort", + "machine_real_restart", ++ "rewind_stack_do_exit", + }; + + if (func->bind == STB_WEAK) diff --git a/patch/kernel/sunxi-next/patch-4.19.42-43.patch b/patch/kernel/sunxi-next/patch-4.19.42-43.patch new file mode 100644 index 0000000000..e914c0a7aa --- /dev/null +++ b/patch/kernel/sunxi-next/patch-4.19.42-43.patch @@ -0,0 +1,3611 @@ +diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu +index 73318225a368..8718d4ad227b 100644 +--- a/Documentation/ABI/testing/sysfs-devices-system-cpu ++++ b/Documentation/ABI/testing/sysfs-devices-system-cpu +@@ -477,6 +477,7 @@ What: /sys/devices/system/cpu/vulnerabilities + /sys/devices/system/cpu/vulnerabilities/spectre_v2 + /sys/devices/system/cpu/vulnerabilities/spec_store_bypass + /sys/devices/system/cpu/vulnerabilities/l1tf ++ /sys/devices/system/cpu/vulnerabilities/mds + Date: January 2018 + Contact: Linux kernel mailing list + Description: Information about CPU vulnerabilities +@@ -489,8 +490,7 @@ Description: Information about CPU vulnerabilities + "Vulnerable" CPU is affected and no mitigation in effect + "Mitigation: $M" CPU is affected and mitigation $M is in effect + +- Details about the l1tf file can be found in +- Documentation/admin-guide/l1tf.rst ++ See also: Documentation/admin-guide/hw-vuln/index.rst + + What: /sys/devices/system/cpu/smt + /sys/devices/system/cpu/smt/active +diff --git a/Documentation/admin-guide/hw-vuln/index.rst b/Documentation/admin-guide/hw-vuln/index.rst +new file mode 100644 +index 000000000000..ffc064c1ec68 +--- /dev/null ++++ b/Documentation/admin-guide/hw-vuln/index.rst +@@ -0,0 +1,13 @@ ++======================== ++Hardware vulnerabilities ++======================== ++ ++This section describes CPU vulnerabilities and provides an overview of the ++possible mitigations along with guidance for selecting mitigations if they ++are configurable at compile, boot or run time. ++ ++.. toctree:: ++ :maxdepth: 1 ++ ++ l1tf ++ mds +diff --git a/Documentation/admin-guide/hw-vuln/l1tf.rst b/Documentation/admin-guide/hw-vuln/l1tf.rst +new file mode 100644 +index 000000000000..31653a9f0e1b +--- /dev/null ++++ b/Documentation/admin-guide/hw-vuln/l1tf.rst +@@ -0,0 +1,615 @@ ++L1TF - L1 Terminal Fault ++======================== ++ ++L1 Terminal Fault is a hardware vulnerability which allows unprivileged ++speculative access to data which is available in the Level 1 Data Cache ++when the page table entry controlling the virtual address, which is used ++for the access, has the Present bit cleared or other reserved bits set. ++ ++Affected processors ++------------------- ++ ++This vulnerability affects a wide range of Intel processors. The ++vulnerability is not present on: ++ ++ - Processors from AMD, Centaur and other non Intel vendors ++ ++ - Older processor models, where the CPU family is < 6 ++ ++ - A range of Intel ATOM processors (Cedarview, Cloverview, Lincroft, ++ Penwell, Pineview, Silvermont, Airmont, Merrifield) ++ ++ - The Intel XEON PHI family ++ ++ - Intel processors which have the ARCH_CAP_RDCL_NO bit set in the ++ IA32_ARCH_CAPABILITIES MSR. If the bit is set the CPU is not affected ++ by the Meltdown vulnerability either. These CPUs should become ++ available by end of 2018. ++ ++Whether a processor is affected or not can be read out from the L1TF ++vulnerability file in sysfs. See :ref:`l1tf_sys_info`. ++ ++Related CVEs ++------------ ++ ++The following CVE entries are related to the L1TF vulnerability: ++ ++ ============= ================= ============================== ++ CVE-2018-3615 L1 Terminal Fault SGX related aspects ++ CVE-2018-3620 L1 Terminal Fault OS, SMM related aspects ++ CVE-2018-3646 L1 Terminal Fault Virtualization related aspects ++ ============= ================= ============================== ++ ++Problem ++------- ++ ++If an instruction accesses a virtual address for which the relevant page ++table entry (PTE) has the Present bit cleared or other reserved bits set, ++then speculative execution ignores the invalid PTE and loads the referenced ++data if it is present in the Level 1 Data Cache, as if the page referenced ++by the address bits in the PTE was still present and accessible. ++ ++While this is a purely speculative mechanism and the instruction will raise ++a page fault when it is retired eventually, the pure act of loading the ++data and making it available to other speculative instructions opens up the ++opportunity for side channel attacks to unprivileged malicious code, ++similar to the Meltdown attack. ++ ++While Meltdown breaks the user space to kernel space protection, L1TF ++allows to attack any physical memory address in the system and the attack ++works across all protection domains. It allows an attack of SGX and also ++works from inside virtual machines because the speculation bypasses the ++extended page table (EPT) protection mechanism. ++ ++ ++Attack scenarios ++---------------- ++ ++1. Malicious user space ++^^^^^^^^^^^^^^^^^^^^^^^ ++ ++ Operating Systems store arbitrary information in the address bits of a ++ PTE which is marked non present. This allows a malicious user space ++ application to attack the physical memory to which these PTEs resolve. ++ In some cases user-space can maliciously influence the information ++ encoded in the address bits of the PTE, thus making attacks more ++ deterministic and more practical. ++ ++ The Linux kernel contains a mitigation for this attack vector, PTE ++ inversion, which is permanently enabled and has no performance ++ impact. The kernel ensures that the address bits of PTEs, which are not ++ marked present, never point to cacheable physical memory space. ++ ++ A system with an up to date kernel is protected against attacks from ++ malicious user space applications. ++ ++2. Malicious guest in a virtual machine ++^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ++ The fact that L1TF breaks all domain protections allows malicious guest ++ OSes, which can control the PTEs directly, and malicious guest user ++ space applications, which run on an unprotected guest kernel lacking the ++ PTE inversion mitigation for L1TF, to attack physical host memory. ++ ++ A special aspect of L1TF in the context of virtualization is symmetric ++ multi threading (SMT). The Intel implementation of SMT is called ++ HyperThreading. The fact that Hyperthreads on the affected processors ++ share the L1 Data Cache (L1D) is important for this. As the flaw allows ++ only to attack data which is present in L1D, a malicious guest running ++ on one Hyperthread can attack the data which is brought into the L1D by ++ the context which runs on the sibling Hyperthread of the same physical ++ core. This context can be host OS, host user space or a different guest. ++ ++ If the processor does not support Extended Page Tables, the attack is ++ only possible, when the hypervisor does not sanitize the content of the ++ effective (shadow) page tables. ++ ++ While solutions exist to mitigate these attack vectors fully, these ++ mitigations are not enabled by default in the Linux kernel because they ++ can affect performance significantly. The kernel provides several ++ mechanisms which can be utilized to address the problem depending on the ++ deployment scenario. The mitigations, their protection scope and impact ++ are described in the next sections. ++ ++ The default mitigations and the rationale for choosing them are explained ++ at the end of this document. See :ref:`default_mitigations`. ++ ++.. _l1tf_sys_info: ++ ++L1TF system information ++----------------------- ++ ++The Linux kernel provides a sysfs interface to enumerate the current L1TF ++status of the system: whether the system is vulnerable, and which ++mitigations are active. The relevant sysfs file is: ++ ++/sys/devices/system/cpu/vulnerabilities/l1tf ++ ++The possible values in this file are: ++ ++ =========================== =============================== ++ 'Not affected' The processor is not vulnerable ++ 'Mitigation: PTE Inversion' The host protection is active ++ =========================== =============================== ++ ++If KVM/VMX is enabled and the processor is vulnerable then the following ++information is appended to the 'Mitigation: PTE Inversion' part: ++ ++ - SMT status: ++ ++ ===================== ================ ++ 'VMX: SMT vulnerable' SMT is enabled ++ 'VMX: SMT disabled' SMT is disabled ++ ===================== ================ ++ ++ - L1D Flush mode: ++ ++ ================================ ==================================== ++ 'L1D vulnerable' L1D flushing is disabled ++ ++ 'L1D conditional cache flushes' L1D flush is conditionally enabled ++ ++ 'L1D cache flushes' L1D flush is unconditionally enabled ++ ================================ ==================================== ++ ++The resulting grade of protection is discussed in the following sections. ++ ++ ++Host mitigation mechanism ++------------------------- ++ ++The kernel is unconditionally protected against L1TF attacks from malicious ++user space running on the host. ++ ++ ++Guest mitigation mechanisms ++--------------------------- ++ ++.. _l1d_flush: ++ ++1. L1D flush on VMENTER ++^^^^^^^^^^^^^^^^^^^^^^^ ++ ++ To make sure that a guest cannot attack data which is present in the L1D ++ the hypervisor flushes the L1D before entering the guest. ++ ++ Flushing the L1D evicts not only the data which should not be accessed ++ by a potentially malicious guest, it also flushes the guest ++ data. Flushing the L1D has a performance impact as the processor has to ++ bring the flushed guest data back into the L1D. Depending on the ++ frequency of VMEXIT/VMENTER and the type of computations in the guest ++ performance degradation in the range of 1% to 50% has been observed. For ++ scenarios where guest VMEXIT/VMENTER are rare the performance impact is ++ minimal. Virtio and mechanisms like posted interrupts are designed to ++ confine the VMEXITs to a bare minimum, but specific configurations and ++ application scenarios might still suffer from a high VMEXIT rate. ++ ++ The kernel provides two L1D flush modes: ++ - conditional ('cond') ++ - unconditional ('always') ++ ++ The conditional mode avoids L1D flushing after VMEXITs which execute ++ only audited code paths before the corresponding VMENTER. These code ++ paths have been verified that they cannot expose secrets or other ++ interesting data to an attacker, but they can leak information about the ++ address space layout of the hypervisor. ++ ++ Unconditional mode flushes L1D on all VMENTER invocations and provides ++ maximum protection. It has a higher overhead than the conditional ++ mode. The overhead cannot be quantified correctly as it depends on the ++ workload scenario and the resulting number of VMEXITs. ++ ++ The general recommendation is to enable L1D flush on VMENTER. The kernel ++ defaults to conditional mode on affected processors. ++ ++ **Note**, that L1D flush does not prevent the SMT problem because the ++ sibling thread will also bring back its data into the L1D which makes it ++ attackable again. ++ ++ L1D flush can be controlled by the administrator via the kernel command ++ line and sysfs control files. See :ref:`mitigation_control_command_line` ++ and :ref:`mitigation_control_kvm`. ++ ++.. _guest_confinement: ++ ++2. Guest VCPU confinement to dedicated physical cores ++^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ++ To address the SMT problem, it is possible to make a guest or a group of ++ guests affine to one or more physical cores. The proper mechanism for ++ that is to utilize exclusive cpusets to ensure that no other guest or ++ host tasks can run on these cores. ++ ++ If only a single guest or related guests run on sibling SMT threads on ++ the same physical core then they can only attack their own memory and ++ restricted parts of the host memory. ++ ++ Host memory is attackable, when one of the sibling SMT threads runs in ++ host OS (hypervisor) context and the other in guest context. The amount ++ of valuable information from the host OS context depends on the context ++ which the host OS executes, i.e. interrupts, soft interrupts and kernel ++ threads. The amount of valuable data from these contexts cannot be ++ declared as non-interesting for an attacker without deep inspection of ++ the code. ++ ++ **Note**, that assigning guests to a fixed set of physical cores affects ++ the ability of the scheduler to do load balancing and might have ++ negative effects on CPU utilization depending on the hosting ++ scenario. Disabling SMT might be a viable alternative for particular ++ scenarios. ++ ++ For further information about confining guests to a single or to a group ++ of cores consult the cpusets documentation: ++ ++ https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt ++ ++.. _interrupt_isolation: ++ ++3. Interrupt affinity ++^^^^^^^^^^^^^^^^^^^^^ ++ ++ Interrupts can be made affine to logical CPUs. This is not universally ++ true because there are types of interrupts which are truly per CPU ++ interrupts, e.g. the local timer interrupt. Aside of that multi queue ++ devices affine their interrupts to single CPUs or groups of CPUs per ++ queue without allowing the administrator to control the affinities. ++ ++ Moving the interrupts, which can be affinity controlled, away from CPUs ++ which run untrusted guests, reduces the attack vector space. ++ ++ Whether the interrupts with are affine to CPUs, which run untrusted ++ guests, provide interesting data for an attacker depends on the system ++ configuration and the scenarios which run on the system. While for some ++ of the interrupts it can be assumed that they won't expose interesting ++ information beyond exposing hints about the host OS memory layout, there ++ is no way to make general assumptions. ++ ++ Interrupt affinity can be controlled by the administrator via the ++ /proc/irq/$NR/smp_affinity[_list] files. Limited documentation is ++ available at: ++ ++ https://www.kernel.org/doc/Documentation/IRQ-affinity.txt ++ ++.. _smt_control: ++ ++4. SMT control ++^^^^^^^^^^^^^^ ++ ++ To prevent the SMT issues of L1TF it might be necessary to disable SMT ++ completely. Disabling SMT can have a significant performance impact, but ++ the impact depends on the hosting scenario and the type of workloads. ++ The impact of disabling SMT needs also to be weighted against the impact ++ of other mitigation solutions like confining guests to dedicated cores. ++ ++ The kernel provides a sysfs interface to retrieve the status of SMT and ++ to control it. It also provides a kernel command line interface to ++ control SMT. ++ ++ The kernel command line interface consists of the following options: ++ ++ =========== ========================================================== ++ nosmt Affects the bring up of the secondary CPUs during boot. The ++ kernel tries to bring all present CPUs online during the ++ boot process. "nosmt" makes sure that from each physical ++ core only one - the so called primary (hyper) thread is ++ activated. Due to a design flaw of Intel processors related ++ to Machine Check Exceptions the non primary siblings have ++ to be brought up at least partially and are then shut down ++ again. "nosmt" can be undone via the sysfs interface. ++ ++ nosmt=force Has the same effect as "nosmt" but it does not allow to ++ undo the SMT disable via the sysfs interface. ++ =========== ========================================================== ++ ++ The sysfs interface provides two files: ++ ++ - /sys/devices/system/cpu/smt/control ++ - /sys/devices/system/cpu/smt/active ++ ++ /sys/devices/system/cpu/smt/control: ++ ++ This file allows to read out the SMT control state and provides the ++ ability to disable or (re)enable SMT. The possible states are: ++ ++ ============== =================================================== ++ on SMT is supported by the CPU and enabled. All ++ logical CPUs can be onlined and offlined without ++ restrictions. ++ ++ off SMT is supported by the CPU and disabled. Only ++ the so called primary SMT threads can be onlined ++ and offlined without restrictions. An attempt to ++ online a non-primary sibling is rejected ++ ++ forceoff Same as 'off' but the state cannot be controlled. ++ Attempts to write to the control file are rejected. ++ ++ notsupported The processor does not support SMT. It's therefore ++ not affected by the SMT implications of L1TF. ++ Attempts to write to the control file are rejected. ++ ============== =================================================== ++ ++ The possible states which can be written into this file to control SMT ++ state are: ++ ++ - on ++ - off ++ - forceoff ++ ++ /sys/devices/system/cpu/smt/active: ++ ++ This file reports whether SMT is enabled and active, i.e. if on any ++ physical core two or more sibling threads are online. ++ ++ SMT control is also possible at boot time via the l1tf kernel command ++ line parameter in combination with L1D flush control. See ++ :ref:`mitigation_control_command_line`. ++ ++5. Disabling EPT ++^^^^^^^^^^^^^^^^ ++ ++ Disabling EPT for virtual machines provides full mitigation for L1TF even ++ with SMT enabled, because the effective page tables for guests are ++ managed and sanitized by the hypervisor. Though disabling EPT has a ++ significant performance impact especially when the Meltdown mitigation ++ KPTI is enabled. ++ ++ EPT can be disabled in the hypervisor via the 'kvm-intel.ept' parameter. ++ ++There is ongoing research and development for new mitigation mechanisms to ++address the performance impact of disabling SMT or EPT. ++ ++.. _mitigation_control_command_line: ++ ++Mitigation control on the kernel command line ++--------------------------------------------- ++ ++The kernel command line allows to control the L1TF mitigations at boot ++time with the option "l1tf=". The valid arguments for this option are: ++ ++ ============ ============================================================= ++ full Provides all available mitigations for the L1TF ++ vulnerability. Disables SMT and enables all mitigations in ++ the hypervisors, i.e. unconditional L1D flushing ++ ++ SMT control and L1D flush control via the sysfs interface ++ is still possible after boot. Hypervisors will issue a ++ warning when the first VM is started in a potentially ++ insecure configuration, i.e. SMT enabled or L1D flush ++ disabled. ++ ++ full,force Same as 'full', but disables SMT and L1D flush runtime ++ control. Implies the 'nosmt=force' command line option. ++ (i.e. sysfs control of SMT is disabled.) ++ ++ flush Leaves SMT enabled and enables the default hypervisor ++ mitigation, i.e. conditional L1D flushing ++ ++ SMT control and L1D flush control via the sysfs interface ++ is still possible after boot. Hypervisors will issue a ++ warning when the first VM is started in a potentially ++ insecure configuration, i.e. SMT enabled or L1D flush ++ disabled. ++ ++ flush,nosmt Disables SMT and enables the default hypervisor mitigation, ++ i.e. conditional L1D flushing. ++ ++ SMT control and L1D flush control via the sysfs interface ++ is still possible after boot. Hypervisors will issue a ++ warning when the first VM is started in a potentially ++ insecure configuration, i.e. SMT enabled or L1D flush ++ disabled. ++ ++ flush,nowarn Same as 'flush', but hypervisors will not warn when a VM is ++ started in a potentially insecure configuration. ++ ++ off Disables hypervisor mitigations and doesn't emit any ++ warnings. ++ It also drops the swap size and available RAM limit restrictions ++ on both hypervisor and bare metal. ++ ++ ============ ============================================================= ++ ++The default is 'flush'. For details about L1D flushing see :ref:`l1d_flush`. ++ ++ ++.. _mitigation_control_kvm: ++ ++Mitigation control for KVM - module parameter ++------------------------------------------------------------- ++ ++The KVM hypervisor mitigation mechanism, flushing the L1D cache when ++entering a guest, can be controlled with a module parameter. ++ ++The option/parameter is "kvm-intel.vmentry_l1d_flush=". It takes the ++following arguments: ++ ++ ============ ============================================================== ++ always L1D cache flush on every VMENTER. ++ ++ cond Flush L1D on VMENTER only when the code between VMEXIT and ++ VMENTER can leak host memory which is considered ++ interesting for an attacker. This still can leak host memory ++ which allows e.g. to determine the hosts address space layout. ++ ++ never Disables the mitigation ++ ============ ============================================================== ++ ++The parameter can be provided on the kernel command line, as a module ++parameter when loading the modules and at runtime modified via the sysfs ++file: ++ ++/sys/module/kvm_intel/parameters/vmentry_l1d_flush ++ ++The default is 'cond'. If 'l1tf=full,force' is given on the kernel command ++line, then 'always' is enforced and the kvm-intel.vmentry_l1d_flush ++module parameter is ignored and writes to the sysfs file are rejected. ++ ++.. _mitigation_selection: ++ ++Mitigation selection guide ++-------------------------- ++ ++1. No virtualization in use ++^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ++ The system is protected by the kernel unconditionally and no further ++ action is required. ++ ++2. Virtualization with trusted guests ++^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ++ If the guest comes from a trusted source and the guest OS kernel is ++ guaranteed to have the L1TF mitigations in place the system is fully ++ protected against L1TF and no further action is required. ++ ++ To avoid the overhead of the default L1D flushing on VMENTER the ++ administrator can disable the flushing via the kernel command line and ++ sysfs control files. See :ref:`mitigation_control_command_line` and ++ :ref:`mitigation_control_kvm`. ++ ++ ++3. Virtualization with untrusted guests ++^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ++3.1. SMT not supported or disabled ++"""""""""""""""""""""""""""""""""" ++ ++ If SMT is not supported by the processor or disabled in the BIOS or by ++ the kernel, it's only required to enforce L1D flushing on VMENTER. ++ ++ Conditional L1D flushing is the default behaviour and can be tuned. See ++ :ref:`mitigation_control_command_line` and :ref:`mitigation_control_kvm`. ++ ++3.2. EPT not supported or disabled ++"""""""""""""""""""""""""""""""""" ++ ++ If EPT is not supported by the processor or disabled in the hypervisor, ++ the system is fully protected. SMT can stay enabled and L1D flushing on ++ VMENTER is not required. ++ ++ EPT can be disabled in the hypervisor via the 'kvm-intel.ept' parameter. ++ ++3.3. SMT and EPT supported and active ++""""""""""""""""""""""""""""""""""""" ++ ++ If SMT and EPT are supported and active then various degrees of ++ mitigations can be employed: ++ ++ - L1D flushing on VMENTER: ++ ++ L1D flushing on VMENTER is the minimal protection requirement, but it ++ is only potent in combination with other mitigation methods. ++ ++ Conditional L1D flushing is the default behaviour and can be tuned. See ++ :ref:`mitigation_control_command_line` and :ref:`mitigation_control_kvm`. ++ ++ - Guest confinement: ++ ++ Confinement of guests to a single or a group of physical cores which ++ are not running any other processes, can reduce the attack surface ++ significantly, but interrupts, soft interrupts and kernel threads can ++ still expose valuable data to a potential attacker. See ++ :ref:`guest_confinement`. ++ ++ - Interrupt isolation: ++ ++ Isolating the guest CPUs from interrupts can reduce the attack surface ++ further, but still allows a malicious guest to explore a limited amount ++ of host physical memory. This can at least be used to gain knowledge ++ about the host address space layout. The interrupts which have a fixed ++ affinity to the CPUs which run the untrusted guests can depending on ++ the scenario still trigger soft interrupts and schedule kernel threads ++ which might expose valuable information. See ++ :ref:`interrupt_isolation`. ++ ++The above three mitigation methods combined can provide protection to a ++certain degree, but the risk of the remaining attack surface has to be ++carefully analyzed. For full protection the following methods are ++available: ++ ++ - Disabling SMT: ++ ++ Disabling SMT and enforcing the L1D flushing provides the maximum ++ amount of protection. This mitigation is not depending on any of the ++ above mitigation methods. ++ ++ SMT control and L1D flushing can be tuned by the command line ++ parameters 'nosmt', 'l1tf', 'kvm-intel.vmentry_l1d_flush' and at run ++ time with the matching sysfs control files. See :ref:`smt_control`, ++ :ref:`mitigation_control_command_line` and ++ :ref:`mitigation_control_kvm`. ++ ++ - Disabling EPT: ++ ++ Disabling EPT provides the maximum amount of protection as well. It is ++ not depending on any of the above mitigation methods. SMT can stay ++ enabled and L1D flushing is not required, but the performance impact is ++ significant. ++ ++ EPT can be disabled in the hypervisor via the 'kvm-intel.ept' ++ parameter. ++ ++3.4. Nested virtual machines ++"""""""""""""""""""""""""""" ++ ++When nested virtualization is in use, three operating systems are involved: ++the bare metal hypervisor, the nested hypervisor and the nested virtual ++machine. VMENTER operations from the nested hypervisor into the nested ++guest will always be processed by the bare metal hypervisor. If KVM is the ++bare metal hypervisor it will: ++ ++ - Flush the L1D cache on every switch from the nested hypervisor to the ++ nested virtual machine, so that the nested hypervisor's secrets are not ++ exposed to the nested virtual machine; ++ ++ - Flush the L1D cache on every switch from the nested virtual machine to ++ the nested hypervisor; this is a complex operation, and flushing the L1D ++ cache avoids that the bare metal hypervisor's secrets are exposed to the ++ nested virtual machine; ++ ++ - Instruct the nested hypervisor to not perform any L1D cache flush. This ++ is an optimization to avoid double L1D flushing. ++ ++ ++.. _default_mitigations: ++ ++Default mitigations ++------------------- ++ ++ The kernel default mitigations for vulnerable processors are: ++ ++ - PTE inversion to protect against malicious user space. This is done ++ unconditionally and cannot be controlled. The swap storage is limited ++ to ~16TB. ++ ++ - L1D conditional flushing on VMENTER when EPT is enabled for ++ a guest. ++ ++ The kernel does not by default enforce the disabling of SMT, which leaves ++ SMT systems vulnerable when running untrusted guests with EPT enabled. ++ ++ The rationale for this choice is: ++ ++ - Force disabling SMT can break existing setups, especially with ++ unattended updates. ++ ++ - If regular users run untrusted guests on their machine, then L1TF is ++ just an add on to other malware which might be embedded in an untrusted ++ guest, e.g. spam-bots or attacks on the local network. ++ ++ There is no technical way to prevent a user from running untrusted code ++ on their machines blindly. ++ ++ - It's technically extremely unlikely and from today's knowledge even ++ impossible that L1TF can be exploited via the most popular attack ++ mechanisms like JavaScript because these mechanisms have no way to ++ control PTEs. If this would be possible and not other mitigation would ++ be possible, then the default might be different. ++ ++ - The administrators of cloud and hosting setups have to carefully ++ analyze the risk for their scenarios and make the appropriate ++ mitigation choices, which might even vary across their deployed ++ machines and also result in other changes of their overall setup. ++ There is no way for the kernel to provide a sensible default for this ++ kind of scenarios. +diff --git a/Documentation/admin-guide/hw-vuln/mds.rst b/Documentation/admin-guide/hw-vuln/mds.rst +new file mode 100644 +index 000000000000..e3a796c0d3a2 +--- /dev/null ++++ b/Documentation/admin-guide/hw-vuln/mds.rst +@@ -0,0 +1,308 @@ ++MDS - Microarchitectural Data Sampling ++====================================== ++ ++Microarchitectural Data Sampling is a hardware vulnerability which allows ++unprivileged speculative access to data which is available in various CPU ++internal buffers. ++ ++Affected processors ++------------------- ++ ++This vulnerability affects a wide range of Intel processors. The ++vulnerability is not present on: ++ ++ - Processors from AMD, Centaur and other non Intel vendors ++ ++ - Older processor models, where the CPU family is < 6 ++ ++ - Some Atoms (Bonnell, Saltwell, Goldmont, GoldmontPlus) ++ ++ - Intel processors which have the ARCH_CAP_MDS_NO bit set in the ++ IA32_ARCH_CAPABILITIES MSR. ++ ++Whether a processor is affected or not can be read out from the MDS ++vulnerability file in sysfs. See :ref:`mds_sys_info`. ++ ++Not all processors are affected by all variants of MDS, but the mitigation ++is identical for all of them so the kernel treats them as a single ++vulnerability. ++ ++Related CVEs ++------------ ++ ++The following CVE entries are related to the MDS vulnerability: ++ ++ ============== ===== =================================================== ++ CVE-2018-12126 MSBDS Microarchitectural Store Buffer Data Sampling ++ CVE-2018-12130 MFBDS Microarchitectural Fill Buffer Data Sampling ++ CVE-2018-12127 MLPDS Microarchitectural Load Port Data Sampling ++ CVE-2019-11091 MDSUM Microarchitectural Data Sampling Uncacheable Memory ++ ============== ===== =================================================== ++ ++Problem ++------- ++ ++When performing store, load, L1 refill operations, processors write data ++into temporary microarchitectural structures (buffers). The data in the ++buffer can be forwarded to load operations as an optimization. ++ ++Under certain conditions, usually a fault/assist caused by a load ++operation, data unrelated to the load memory address can be speculatively ++forwarded from the buffers. Because the load operation causes a fault or ++assist and its result will be discarded, the forwarded data will not cause ++incorrect program execution or state changes. But a malicious operation ++may be able to forward this speculative data to a disclosure gadget which ++allows in turn to infer the value via a cache side channel attack. ++ ++Because the buffers are potentially shared between Hyper-Threads cross ++Hyper-Thread attacks are possible. ++ ++Deeper technical information is available in the MDS specific x86 ++architecture section: :ref:`Documentation/x86/mds.rst `. ++ ++ ++Attack scenarios ++---------------- ++ ++Attacks against the MDS vulnerabilities can be mounted from malicious non ++priviledged user space applications running on hosts or guest. Malicious ++guest OSes can obviously mount attacks as well. ++ ++Contrary to other speculation based vulnerabilities the MDS vulnerability ++does not allow the attacker to control the memory target address. As a ++consequence the attacks are purely sampling based, but as demonstrated with ++the TLBleed attack samples can be postprocessed successfully. ++ ++Web-Browsers ++^^^^^^^^^^^^ ++ ++ It's unclear whether attacks through Web-Browsers are possible at ++ all. The exploitation through Java-Script is considered very unlikely, ++ but other widely used web technologies like Webassembly could possibly be ++ abused. ++ ++ ++.. _mds_sys_info: ++ ++MDS system information ++----------------------- ++ ++The Linux kernel provides a sysfs interface to enumerate the current MDS ++status of the system: whether the system is vulnerable, and which ++mitigations are active. The relevant sysfs file is: ++ ++/sys/devices/system/cpu/vulnerabilities/mds ++ ++The possible values in this file are: ++ ++ .. list-table:: ++ ++ * - 'Not affected' ++ - The processor is not vulnerable ++ * - 'Vulnerable' ++ - The processor is vulnerable, but no mitigation enabled ++ * - 'Vulnerable: Clear CPU buffers attempted, no microcode' ++ - The processor is vulnerable but microcode is not updated. ++ ++ The mitigation is enabled on a best effort basis. See :ref:`vmwerv` ++ * - 'Mitigation: Clear CPU buffers' ++ - The processor is vulnerable and the CPU buffer clearing mitigation is ++ enabled. ++ ++If the processor is vulnerable then the following information is appended ++to the above information: ++ ++ ======================== ============================================ ++ 'SMT vulnerable' SMT is enabled ++ 'SMT mitigated' SMT is enabled and mitigated ++ 'SMT disabled' SMT is disabled ++ 'SMT Host state unknown' Kernel runs in a VM, Host SMT state unknown ++ ======================== ============================================ ++ ++.. _vmwerv: ++ ++Best effort mitigation mode ++^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ++ If the processor is vulnerable, but the availability of the microcode based ++ mitigation mechanism is not advertised via CPUID the kernel selects a best ++ effort mitigation mode. This mode invokes the mitigation instructions ++ without a guarantee that they clear the CPU buffers. ++ ++ This is done to address virtualization scenarios where the host has the ++ microcode update applied, but the hypervisor is not yet updated to expose ++ the CPUID to the guest. If the host has updated microcode the protection ++ takes effect otherwise a few cpu cycles are wasted pointlessly. ++ ++ The state in the mds sysfs file reflects this situation accordingly. ++ ++ ++Mitigation mechanism ++------------------------- ++ ++The kernel detects the affected CPUs and the presence of the microcode ++which is required. ++ ++If a CPU is affected and the microcode is available, then the kernel ++enables the mitigation by default. The mitigation can be controlled at boot ++time via a kernel command line option. See ++:ref:`mds_mitigation_control_command_line`. ++ ++.. _cpu_buffer_clear: ++ ++CPU buffer clearing ++^^^^^^^^^^^^^^^^^^^ ++ ++ The mitigation for MDS clears the affected CPU buffers on return to user ++ space and when entering a guest. ++ ++ If SMT is enabled it also clears the buffers on idle entry when the CPU ++ is only affected by MSBDS and not any other MDS variant, because the ++ other variants cannot be protected against cross Hyper-Thread attacks. ++ ++ For CPUs which are only affected by MSBDS the user space, guest and idle ++ transition mitigations are sufficient and SMT is not affected. ++ ++.. _virt_mechanism: ++ ++Virtualization mitigation ++^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ++ The protection for host to guest transition depends on the L1TF ++ vulnerability of the CPU: ++ ++ - CPU is affected by L1TF: ++ ++ If the L1D flush mitigation is enabled and up to date microcode is ++ available, the L1D flush mitigation is automatically protecting the ++ guest transition. ++ ++ If the L1D flush mitigation is disabled then the MDS mitigation is ++ invoked explicit when the host MDS mitigation is enabled. ++ ++ For details on L1TF and virtualization see: ++ :ref:`Documentation/admin-guide/hw-vuln//l1tf.rst `. ++ ++ - CPU is not affected by L1TF: ++ ++ CPU buffers are flushed before entering the guest when the host MDS ++ mitigation is enabled. ++ ++ The resulting MDS protection matrix for the host to guest transition: ++ ++ ============ ===== ============= ============ ================= ++ L1TF MDS VMX-L1FLUSH Host MDS MDS-State ++ ++ Don't care No Don't care N/A Not affected ++ ++ Yes Yes Disabled Off Vulnerable ++ ++ Yes Yes Disabled Full Mitigated ++ ++ Yes Yes Enabled Don't care Mitigated ++ ++ No Yes N/A Off Vulnerable ++ ++ No Yes N/A Full Mitigated ++ ============ ===== ============= ============ ================= ++ ++ This only covers the host to guest transition, i.e. prevents leakage from ++ host to guest, but does not protect the guest internally. Guests need to ++ have their own protections. ++ ++.. _xeon_phi: ++ ++XEON PHI specific considerations ++^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ++ The XEON PHI processor family is affected by MSBDS which can be exploited ++ cross Hyper-Threads when entering idle states. Some XEON PHI variants allow ++ to use MWAIT in user space (Ring 3) which opens an potential attack vector ++ for malicious user space. The exposure can be disabled on the kernel ++ command line with the 'ring3mwait=disable' command line option. ++ ++ XEON PHI is not affected by the other MDS variants and MSBDS is mitigated ++ before the CPU enters a idle state. As XEON PHI is not affected by L1TF ++ either disabling SMT is not required for full protection. ++ ++.. _mds_smt_control: ++ ++SMT control ++^^^^^^^^^^^ ++ ++ All MDS variants except MSBDS can be attacked cross Hyper-Threads. That ++ means on CPUs which are affected by MFBDS or MLPDS it is necessary to ++ disable SMT for full protection. These are most of the affected CPUs; the ++ exception is XEON PHI, see :ref:`xeon_phi`. ++ ++ Disabling SMT can have a significant performance impact, but the impact ++ depends on the type of workloads. ++ ++ See the relevant chapter in the L1TF mitigation documentation for details: ++ :ref:`Documentation/admin-guide/hw-vuln/l1tf.rst `. ++ ++ ++.. _mds_mitigation_control_command_line: ++ ++Mitigation control on the kernel command line ++--------------------------------------------- ++ ++The kernel command line allows to control the MDS mitigations at boot ++time with the option "mds=". The valid arguments for this option are: ++ ++ ============ ============================================================= ++ full If the CPU is vulnerable, enable all available mitigations ++ for the MDS vulnerability, CPU buffer clearing on exit to ++ userspace and when entering a VM. Idle transitions are ++ protected as well if SMT is enabled. ++ ++ It does not automatically disable SMT. ++ ++ full,nosmt The same as mds=full, with SMT disabled on vulnerable ++ CPUs. This is the complete mitigation. ++ ++ off Disables MDS mitigations completely. ++ ++ ============ ============================================================= ++ ++Not specifying this option is equivalent to "mds=full". ++ ++ ++Mitigation selection guide ++-------------------------- ++ ++1. Trusted userspace ++^^^^^^^^^^^^^^^^^^^^ ++ ++ If all userspace applications are from a trusted source and do not ++ execute untrusted code which is supplied externally, then the mitigation ++ can be disabled. ++ ++ ++2. Virtualization with trusted guests ++^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ++ The same considerations as above versus trusted user space apply. ++ ++3. Virtualization with untrusted guests ++^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ++ The protection depends on the state of the L1TF mitigations. ++ See :ref:`virt_mechanism`. ++ ++ If the MDS mitigation is enabled and SMT is disabled, guest to host and ++ guest to guest attacks are prevented. ++ ++.. _mds_default_mitigations: ++ ++Default mitigations ++------------------- ++ ++ The kernel default mitigations for vulnerable processors are: ++ ++ - Enable CPU buffer clearing ++ ++ The kernel does not by default enforce the disabling of SMT, which leaves ++ SMT systems vulnerable when running untrusted code. The same rationale as ++ for L1TF applies. ++ See :ref:`Documentation/admin-guide/hw-vuln//l1tf.rst `. +diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst +index 0873685bab0f..89abc5057349 100644 +--- a/Documentation/admin-guide/index.rst ++++ b/Documentation/admin-guide/index.rst +@@ -17,14 +17,12 @@ etc. + kernel-parameters + devices + +-This section describes CPU vulnerabilities and provides an overview of the +-possible mitigations along with guidance for selecting mitigations if they +-are configurable at compile, boot or run time. ++This section describes CPU vulnerabilities and their mitigations. + + .. toctree:: + :maxdepth: 1 + +- l1tf ++ hw-vuln/index + + Here is a set of documents aimed at users who are trying to track down + problems and bugs in particular. +diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt +index 8b6567f7cb9b..a29301d6e6c6 100644 +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -2079,7 +2079,7 @@ + + Default is 'flush'. + +- For details see: Documentation/admin-guide/l1tf.rst ++ For details see: Documentation/admin-guide/hw-vuln/l1tf.rst + + l2cr= [PPC] + +@@ -2319,6 +2319,32 @@ + Format: , + Specifies range of consoles to be captured by the MDA. + ++ mds= [X86,INTEL] ++ Control mitigation for the Micro-architectural Data ++ Sampling (MDS) vulnerability. ++ ++ Certain CPUs are vulnerable to an exploit against CPU ++ internal buffers which can forward information to a ++ disclosure gadget under certain conditions. ++ ++ In vulnerable processors, the speculatively ++ forwarded data can be used in a cache side channel ++ attack, to access data to which the attacker does ++ not have direct access. ++ ++ This parameter controls the MDS mitigation. The ++ options are: ++ ++ full - Enable MDS mitigation on vulnerable CPUs ++ full,nosmt - Enable MDS mitigation and disable ++ SMT on vulnerable CPUs ++ off - Unconditionally disable MDS mitigation ++ ++ Not specifying this option is equivalent to ++ mds=full. ++ ++ For details see: Documentation/admin-guide/hw-vuln/mds.rst ++ + mem=nn[KMG] [KNL,BOOT] Force usage of a specific amount of memory + Amount of memory to be used when the kernel is not able + to see the whole system memory or for test. +@@ -2476,6 +2502,40 @@ + in the "bleeding edge" mini2440 support kernel at + http://repo.or.cz/w/linux-2.6/mini2440.git + ++ mitigations= ++ [X86,PPC,S390] Control optional mitigations for CPU ++ vulnerabilities. This is a set of curated, ++ arch-independent options, each of which is an ++ aggregation of existing arch-specific options. ++ ++ off ++ Disable all optional CPU mitigations. This ++ improves system performance, but it may also ++ expose users to several CPU vulnerabilities. ++ Equivalent to: nopti [X86,PPC] ++ nospectre_v1 [PPC] ++ nobp=0 [S390] ++ nospectre_v2 [X86,PPC,S390] ++ spectre_v2_user=off [X86] ++ spec_store_bypass_disable=off [X86,PPC] ++ l1tf=off [X86] ++ mds=off [X86] ++ ++ auto (default) ++ Mitigate all CPU vulnerabilities, but leave SMT ++ enabled, even if it's vulnerable. This is for ++ users who don't want to be surprised by SMT ++ getting disabled across kernel upgrades, or who ++ have other ways of avoiding SMT-based attacks. ++ Equivalent to: (default behavior) ++ ++ auto,nosmt ++ Mitigate all CPU vulnerabilities, disabling SMT ++ if needed. This is for users who always want to ++ be fully mitigated, even if it means losing SMT. ++ Equivalent to: l1tf=flush,nosmt [X86] ++ mds=full,nosmt [X86] ++ + mminit_loglevel= + [KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this + parameter allows control of the logging verbosity for +diff --git a/Documentation/admin-guide/l1tf.rst b/Documentation/admin-guide/l1tf.rst +deleted file mode 100644 +index 9f5924f81f89..000000000000 +--- a/Documentation/admin-guide/l1tf.rst ++++ /dev/null +@@ -1,614 +0,0 @@ +-L1TF - L1 Terminal Fault +-======================== +- +-L1 Terminal Fault is a hardware vulnerability which allows unprivileged +-speculative access to data which is available in the Level 1 Data Cache +-when the page table entry controlling the virtual address, which is used +-for the access, has the Present bit cleared or other reserved bits set. +- +-Affected processors +-------------------- +- +-This vulnerability affects a wide range of Intel processors. The +-vulnerability is not present on: +- +- - Processors from AMD, Centaur and other non Intel vendors +- +- - Older processor models, where the CPU family is < 6 +- +- - A range of Intel ATOM processors (Cedarview, Cloverview, Lincroft, +- Penwell, Pineview, Silvermont, Airmont, Merrifield) +- +- - The Intel XEON PHI family +- +- - Intel processors which have the ARCH_CAP_RDCL_NO bit set in the +- IA32_ARCH_CAPABILITIES MSR. If the bit is set the CPU is not affected +- by the Meltdown vulnerability either. These CPUs should become +- available by end of 2018. +- +-Whether a processor is affected or not can be read out from the L1TF +-vulnerability file in sysfs. See :ref:`l1tf_sys_info`. +- +-Related CVEs +------------- +- +-The following CVE entries are related to the L1TF vulnerability: +- +- ============= ================= ============================== +- CVE-2018-3615 L1 Terminal Fault SGX related aspects +- CVE-2018-3620 L1 Terminal Fault OS, SMM related aspects +- CVE-2018-3646 L1 Terminal Fault Virtualization related aspects +- ============= ================= ============================== +- +-Problem +-------- +- +-If an instruction accesses a virtual address for which the relevant page +-table entry (PTE) has the Present bit cleared or other reserved bits set, +-then speculative execution ignores the invalid PTE and loads the referenced +-data if it is present in the Level 1 Data Cache, as if the page referenced +-by the address bits in the PTE was still present and accessible. +- +-While this is a purely speculative mechanism and the instruction will raise +-a page fault when it is retired eventually, the pure act of loading the +-data and making it available to other speculative instructions opens up the +-opportunity for side channel attacks to unprivileged malicious code, +-similar to the Meltdown attack. +- +-While Meltdown breaks the user space to kernel space protection, L1TF +-allows to attack any physical memory address in the system and the attack +-works across all protection domains. It allows an attack of SGX and also +-works from inside virtual machines because the speculation bypasses the +-extended page table (EPT) protection mechanism. +- +- +-Attack scenarios +----------------- +- +-1. Malicious user space +-^^^^^^^^^^^^^^^^^^^^^^^ +- +- Operating Systems store arbitrary information in the address bits of a +- PTE which is marked non present. This allows a malicious user space +- application to attack the physical memory to which these PTEs resolve. +- In some cases user-space can maliciously influence the information +- encoded in the address bits of the PTE, thus making attacks more +- deterministic and more practical. +- +- The Linux kernel contains a mitigation for this attack vector, PTE +- inversion, which is permanently enabled and has no performance +- impact. The kernel ensures that the address bits of PTEs, which are not +- marked present, never point to cacheable physical memory space. +- +- A system with an up to date kernel is protected against attacks from +- malicious user space applications. +- +-2. Malicious guest in a virtual machine +-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- +- The fact that L1TF breaks all domain protections allows malicious guest +- OSes, which can control the PTEs directly, and malicious guest user +- space applications, which run on an unprotected guest kernel lacking the +- PTE inversion mitigation for L1TF, to attack physical host memory. +- +- A special aspect of L1TF in the context of virtualization is symmetric +- multi threading (SMT). The Intel implementation of SMT is called +- HyperThreading. The fact that Hyperthreads on the affected processors +- share the L1 Data Cache (L1D) is important for this. As the flaw allows +- only to attack data which is present in L1D, a malicious guest running +- on one Hyperthread can attack the data which is brought into the L1D by +- the context which runs on the sibling Hyperthread of the same physical +- core. This context can be host OS, host user space or a different guest. +- +- If the processor does not support Extended Page Tables, the attack is +- only possible, when the hypervisor does not sanitize the content of the +- effective (shadow) page tables. +- +- While solutions exist to mitigate these attack vectors fully, these +- mitigations are not enabled by default in the Linux kernel because they +- can affect performance significantly. The kernel provides several +- mechanisms which can be utilized to address the problem depending on the +- deployment scenario. The mitigations, their protection scope and impact +- are described in the next sections. +- +- The default mitigations and the rationale for choosing them are explained +- at the end of this document. See :ref:`default_mitigations`. +- +-.. _l1tf_sys_info: +- +-L1TF system information +------------------------ +- +-The Linux kernel provides a sysfs interface to enumerate the current L1TF +-status of the system: whether the system is vulnerable, and which +-mitigations are active. The relevant sysfs file is: +- +-/sys/devices/system/cpu/vulnerabilities/l1tf +- +-The possible values in this file are: +- +- =========================== =============================== +- 'Not affected' The processor is not vulnerable +- 'Mitigation: PTE Inversion' The host protection is active +- =========================== =============================== +- +-If KVM/VMX is enabled and the processor is vulnerable then the following +-information is appended to the 'Mitigation: PTE Inversion' part: +- +- - SMT status: +- +- ===================== ================ +- 'VMX: SMT vulnerable' SMT is enabled +- 'VMX: SMT disabled' SMT is disabled +- ===================== ================ +- +- - L1D Flush mode: +- +- ================================ ==================================== +- 'L1D vulnerable' L1D flushing is disabled +- +- 'L1D conditional cache flushes' L1D flush is conditionally enabled +- +- 'L1D cache flushes' L1D flush is unconditionally enabled +- ================================ ==================================== +- +-The resulting grade of protection is discussed in the following sections. +- +- +-Host mitigation mechanism +-------------------------- +- +-The kernel is unconditionally protected against L1TF attacks from malicious +-user space running on the host. +- +- +-Guest mitigation mechanisms +---------------------------- +- +-.. _l1d_flush: +- +-1. L1D flush on VMENTER +-^^^^^^^^^^^^^^^^^^^^^^^ +- +- To make sure that a guest cannot attack data which is present in the L1D +- the hypervisor flushes the L1D before entering the guest. +- +- Flushing the L1D evicts not only the data which should not be accessed +- by a potentially malicious guest, it also flushes the guest +- data. Flushing the L1D has a performance impact as the processor has to +- bring the flushed guest data back into the L1D. Depending on the +- frequency of VMEXIT/VMENTER and the type of computations in the guest +- performance degradation in the range of 1% to 50% has been observed. For +- scenarios where guest VMEXIT/VMENTER are rare the performance impact is +- minimal. Virtio and mechanisms like posted interrupts are designed to +- confine the VMEXITs to a bare minimum, but specific configurations and +- application scenarios might still suffer from a high VMEXIT rate. +- +- The kernel provides two L1D flush modes: +- - conditional ('cond') +- - unconditional ('always') +- +- The conditional mode avoids L1D flushing after VMEXITs which execute +- only audited code paths before the corresponding VMENTER. These code +- paths have been verified that they cannot expose secrets or other +- interesting data to an attacker, but they can leak information about the +- address space layout of the hypervisor. +- +- Unconditional mode flushes L1D on all VMENTER invocations and provides +- maximum protection. It has a higher overhead than the conditional +- mode. The overhead cannot be quantified correctly as it depends on the +- workload scenario and the resulting number of VMEXITs. +- +- The general recommendation is to enable L1D flush on VMENTER. The kernel +- defaults to conditional mode on affected processors. +- +- **Note**, that L1D flush does not prevent the SMT problem because the +- sibling thread will also bring back its data into the L1D which makes it +- attackable again. +- +- L1D flush can be controlled by the administrator via the kernel command +- line and sysfs control files. See :ref:`mitigation_control_command_line` +- and :ref:`mitigation_control_kvm`. +- +-.. _guest_confinement: +- +-2. Guest VCPU confinement to dedicated physical cores +-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- +- To address the SMT problem, it is possible to make a guest or a group of +- guests affine to one or more physical cores. The proper mechanism for +- that is to utilize exclusive cpusets to ensure that no other guest or +- host tasks can run on these cores. +- +- If only a single guest or related guests run on sibling SMT threads on +- the same physical core then they can only attack their own memory and +- restricted parts of the host memory. +- +- Host memory is attackable, when one of the sibling SMT threads runs in +- host OS (hypervisor) context and the other in guest context. The amount +- of valuable information from the host OS context depends on the context +- which the host OS executes, i.e. interrupts, soft interrupts and kernel +- threads. The amount of valuable data from these contexts cannot be +- declared as non-interesting for an attacker without deep inspection of +- the code. +- +- **Note**, that assigning guests to a fixed set of physical cores affects +- the ability of the scheduler to do load balancing and might have +- negative effects on CPU utilization depending on the hosting +- scenario. Disabling SMT might be a viable alternative for particular +- scenarios. +- +- For further information about confining guests to a single or to a group +- of cores consult the cpusets documentation: +- +- https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt +- +-.. _interrupt_isolation: +- +-3. Interrupt affinity +-^^^^^^^^^^^^^^^^^^^^^ +- +- Interrupts can be made affine to logical CPUs. This is not universally +- true because there are types of interrupts which are truly per CPU +- interrupts, e.g. the local timer interrupt. Aside of that multi queue +- devices affine their interrupts to single CPUs or groups of CPUs per +- queue without allowing the administrator to control the affinities. +- +- Moving the interrupts, which can be affinity controlled, away from CPUs +- which run untrusted guests, reduces the attack vector space. +- +- Whether the interrupts with are affine to CPUs, which run untrusted +- guests, provide interesting data for an attacker depends on the system +- configuration and the scenarios which run on the system. While for some +- of the interrupts it can be assumed that they won't expose interesting +- information beyond exposing hints about the host OS memory layout, there +- is no way to make general assumptions. +- +- Interrupt affinity can be controlled by the administrator via the +- /proc/irq/$NR/smp_affinity[_list] files. Limited documentation is +- available at: +- +- https://www.kernel.org/doc/Documentation/IRQ-affinity.txt +- +-.. _smt_control: +- +-4. SMT control +-^^^^^^^^^^^^^^ +- +- To prevent the SMT issues of L1TF it might be necessary to disable SMT +- completely. Disabling SMT can have a significant performance impact, but +- the impact depends on the hosting scenario and the type of workloads. +- The impact of disabling SMT needs also to be weighted against the impact +- of other mitigation solutions like confining guests to dedicated cores. +- +- The kernel provides a sysfs interface to retrieve the status of SMT and +- to control it. It also provides a kernel command line interface to +- control SMT. +- +- The kernel command line interface consists of the following options: +- +- =========== ========================================================== +- nosmt Affects the bring up of the secondary CPUs during boot. The +- kernel tries to bring all present CPUs online during the +- boot process. "nosmt" makes sure that from each physical +- core only one - the so called primary (hyper) thread is +- activated. Due to a design flaw of Intel processors related +- to Machine Check Exceptions the non primary siblings have +- to be brought up at least partially and are then shut down +- again. "nosmt" can be undone via the sysfs interface. +- +- nosmt=force Has the same effect as "nosmt" but it does not allow to +- undo the SMT disable via the sysfs interface. +- =========== ========================================================== +- +- The sysfs interface provides two files: +- +- - /sys/devices/system/cpu/smt/control +- - /sys/devices/system/cpu/smt/active +- +- /sys/devices/system/cpu/smt/control: +- +- This file allows to read out the SMT control state and provides the +- ability to disable or (re)enable SMT. The possible states are: +- +- ============== =================================================== +- on SMT is supported by the CPU and enabled. All +- logical CPUs can be onlined and offlined without +- restrictions. +- +- off SMT is supported by the CPU and disabled. Only +- the so called primary SMT threads can be onlined +- and offlined without restrictions. An attempt to +- online a non-primary sibling is rejected +- +- forceoff Same as 'off' but the state cannot be controlled. +- Attempts to write to the control file are rejected. +- +- notsupported The processor does not support SMT. It's therefore +- not affected by the SMT implications of L1TF. +- Attempts to write to the control file are rejected. +- ============== =================================================== +- +- The possible states which can be written into this file to control SMT +- state are: +- +- - on +- - off +- - forceoff +- +- /sys/devices/system/cpu/smt/active: +- +- This file reports whether SMT is enabled and active, i.e. if on any +- physical core two or more sibling threads are online. +- +- SMT control is also possible at boot time via the l1tf kernel command +- line parameter in combination with L1D flush control. See +- :ref:`mitigation_control_command_line`. +- +-5. Disabling EPT +-^^^^^^^^^^^^^^^^ +- +- Disabling EPT for virtual machines provides full mitigation for L1TF even +- with SMT enabled, because the effective page tables for guests are +- managed and sanitized by the hypervisor. Though disabling EPT has a +- significant performance impact especially when the Meltdown mitigation +- KPTI is enabled. +- +- EPT can be disabled in the hypervisor via the 'kvm-intel.ept' parameter. +- +-There is ongoing research and development for new mitigation mechanisms to +-address the performance impact of disabling SMT or EPT. +- +-.. _mitigation_control_command_line: +- +-Mitigation control on the kernel command line +---------------------------------------------- +- +-The kernel command line allows to control the L1TF mitigations at boot +-time with the option "l1tf=". The valid arguments for this option are: +- +- ============ ============================================================= +- full Provides all available mitigations for the L1TF +- vulnerability. Disables SMT and enables all mitigations in +- the hypervisors, i.e. unconditional L1D flushing +- +- SMT control and L1D flush control via the sysfs interface +- is still possible after boot. Hypervisors will issue a +- warning when the first VM is started in a potentially +- insecure configuration, i.e. SMT enabled or L1D flush +- disabled. +- +- full,force Same as 'full', but disables SMT and L1D flush runtime +- control. Implies the 'nosmt=force' command line option. +- (i.e. sysfs control of SMT is disabled.) +- +- flush Leaves SMT enabled and enables the default hypervisor +- mitigation, i.e. conditional L1D flushing +- +- SMT control and L1D flush control via the sysfs interface +- is still possible after boot. Hypervisors will issue a +- warning when the first VM is started in a potentially +- insecure configuration, i.e. SMT enabled or L1D flush +- disabled. +- +- flush,nosmt Disables SMT and enables the default hypervisor mitigation, +- i.e. conditional L1D flushing. +- +- SMT control and L1D flush control via the sysfs interface +- is still possible after boot. Hypervisors will issue a +- warning when the first VM is started in a potentially +- insecure configuration, i.e. SMT enabled or L1D flush +- disabled. +- +- flush,nowarn Same as 'flush', but hypervisors will not warn when a VM is +- started in a potentially insecure configuration. +- +- off Disables hypervisor mitigations and doesn't emit any +- warnings. +- It also drops the swap size and available RAM limit restrictions +- on both hypervisor and bare metal. +- +- ============ ============================================================= +- +-The default is 'flush'. For details about L1D flushing see :ref:`l1d_flush`. +- +- +-.. _mitigation_control_kvm: +- +-Mitigation control for KVM - module parameter +-------------------------------------------------------------- +- +-The KVM hypervisor mitigation mechanism, flushing the L1D cache when +-entering a guest, can be controlled with a module parameter. +- +-The option/parameter is "kvm-intel.vmentry_l1d_flush=". It takes the +-following arguments: +- +- ============ ============================================================== +- always L1D cache flush on every VMENTER. +- +- cond Flush L1D on VMENTER only when the code between VMEXIT and +- VMENTER can leak host memory which is considered +- interesting for an attacker. This still can leak host memory +- which allows e.g. to determine the hosts address space layout. +- +- never Disables the mitigation +- ============ ============================================================== +- +-The parameter can be provided on the kernel command line, as a module +-parameter when loading the modules and at runtime modified via the sysfs +-file: +- +-/sys/module/kvm_intel/parameters/vmentry_l1d_flush +- +-The default is 'cond'. If 'l1tf=full,force' is given on the kernel command +-line, then 'always' is enforced and the kvm-intel.vmentry_l1d_flush +-module parameter is ignored and writes to the sysfs file are rejected. +- +- +-Mitigation selection guide +--------------------------- +- +-1. No virtualization in use +-^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- +- The system is protected by the kernel unconditionally and no further +- action is required. +- +-2. Virtualization with trusted guests +-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- +- If the guest comes from a trusted source and the guest OS kernel is +- guaranteed to have the L1TF mitigations in place the system is fully +- protected against L1TF and no further action is required. +- +- To avoid the overhead of the default L1D flushing on VMENTER the +- administrator can disable the flushing via the kernel command line and +- sysfs control files. See :ref:`mitigation_control_command_line` and +- :ref:`mitigation_control_kvm`. +- +- +-3. Virtualization with untrusted guests +-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- +-3.1. SMT not supported or disabled +-"""""""""""""""""""""""""""""""""" +- +- If SMT is not supported by the processor or disabled in the BIOS or by +- the kernel, it's only required to enforce L1D flushing on VMENTER. +- +- Conditional L1D flushing is the default behaviour and can be tuned. See +- :ref:`mitigation_control_command_line` and :ref:`mitigation_control_kvm`. +- +-3.2. EPT not supported or disabled +-"""""""""""""""""""""""""""""""""" +- +- If EPT is not supported by the processor or disabled in the hypervisor, +- the system is fully protected. SMT can stay enabled and L1D flushing on +- VMENTER is not required. +- +- EPT can be disabled in the hypervisor via the 'kvm-intel.ept' parameter. +- +-3.3. SMT and EPT supported and active +-""""""""""""""""""""""""""""""""""""" +- +- If SMT and EPT are supported and active then various degrees of +- mitigations can be employed: +- +- - L1D flushing on VMENTER: +- +- L1D flushing on VMENTER is the minimal protection requirement, but it +- is only potent in combination with other mitigation methods. +- +- Conditional L1D flushing is the default behaviour and can be tuned. See +- :ref:`mitigation_control_command_line` and :ref:`mitigation_control_kvm`. +- +- - Guest confinement: +- +- Confinement of guests to a single or a group of physical cores which +- are not running any other processes, can reduce the attack surface +- significantly, but interrupts, soft interrupts and kernel threads can +- still expose valuable data to a potential attacker. See +- :ref:`guest_confinement`. +- +- - Interrupt isolation: +- +- Isolating the guest CPUs from interrupts can reduce the attack surface +- further, but still allows a malicious guest to explore a limited amount +- of host physical memory. This can at least be used to gain knowledge +- about the host address space layout. The interrupts which have a fixed +- affinity to the CPUs which run the untrusted guests can depending on +- the scenario still trigger soft interrupts and schedule kernel threads +- which might expose valuable information. See +- :ref:`interrupt_isolation`. +- +-The above three mitigation methods combined can provide protection to a +-certain degree, but the risk of the remaining attack surface has to be +-carefully analyzed. For full protection the following methods are +-available: +- +- - Disabling SMT: +- +- Disabling SMT and enforcing the L1D flushing provides the maximum +- amount of protection. This mitigation is not depending on any of the +- above mitigation methods. +- +- SMT control and L1D flushing can be tuned by the command line +- parameters 'nosmt', 'l1tf', 'kvm-intel.vmentry_l1d_flush' and at run +- time with the matching sysfs control files. See :ref:`smt_control`, +- :ref:`mitigation_control_command_line` and +- :ref:`mitigation_control_kvm`. +- +- - Disabling EPT: +- +- Disabling EPT provides the maximum amount of protection as well. It is +- not depending on any of the above mitigation methods. SMT can stay +- enabled and L1D flushing is not required, but the performance impact is +- significant. +- +- EPT can be disabled in the hypervisor via the 'kvm-intel.ept' +- parameter. +- +-3.4. Nested virtual machines +-"""""""""""""""""""""""""""" +- +-When nested virtualization is in use, three operating systems are involved: +-the bare metal hypervisor, the nested hypervisor and the nested virtual +-machine. VMENTER operations from the nested hypervisor into the nested +-guest will always be processed by the bare metal hypervisor. If KVM is the +-bare metal hypervisor it wiil: +- +- - Flush the L1D cache on every switch from the nested hypervisor to the +- nested virtual machine, so that the nested hypervisor's secrets are not +- exposed to the nested virtual machine; +- +- - Flush the L1D cache on every switch from the nested virtual machine to +- the nested hypervisor; this is a complex operation, and flushing the L1D +- cache avoids that the bare metal hypervisor's secrets are exposed to the +- nested virtual machine; +- +- - Instruct the nested hypervisor to not perform any L1D cache flush. This +- is an optimization to avoid double L1D flushing. +- +- +-.. _default_mitigations: +- +-Default mitigations +-------------------- +- +- The kernel default mitigations for vulnerable processors are: +- +- - PTE inversion to protect against malicious user space. This is done +- unconditionally and cannot be controlled. The swap storage is limited +- to ~16TB. +- +- - L1D conditional flushing on VMENTER when EPT is enabled for +- a guest. +- +- The kernel does not by default enforce the disabling of SMT, which leaves +- SMT systems vulnerable when running untrusted guests with EPT enabled. +- +- The rationale for this choice is: +- +- - Force disabling SMT can break existing setups, especially with +- unattended updates. +- +- - If regular users run untrusted guests on their machine, then L1TF is +- just an add on to other malware which might be embedded in an untrusted +- guest, e.g. spam-bots or attacks on the local network. +- +- There is no technical way to prevent a user from running untrusted code +- on their machines blindly. +- +- - It's technically extremely unlikely and from today's knowledge even +- impossible that L1TF can be exploited via the most popular attack +- mechanisms like JavaScript because these mechanisms have no way to +- control PTEs. If this would be possible and not other mitigation would +- be possible, then the default might be different. +- +- - The administrators of cloud and hosting setups have to carefully +- analyze the risk for their scenarios and make the appropriate +- mitigation choices, which might even vary across their deployed +- machines and also result in other changes of their overall setup. +- There is no way for the kernel to provide a sensible default for this +- kind of scenarios. +diff --git a/Documentation/index.rst b/Documentation/index.rst +index 5db7e87c7cb1..1cdc139adb40 100644 +--- a/Documentation/index.rst ++++ b/Documentation/index.rst +@@ -104,6 +104,7 @@ implementation. + :maxdepth: 2 + + sh/index ++ x86/index + + Filesystem Documentation + ------------------------ +diff --git a/Documentation/x86/conf.py b/Documentation/x86/conf.py +new file mode 100644 +index 000000000000..33c5c3142e20 +--- /dev/null ++++ b/Documentation/x86/conf.py +@@ -0,0 +1,10 @@ ++# -*- coding: utf-8; mode: python -*- ++ ++project = "X86 architecture specific documentation" ++ ++tags.add("subproject") ++ ++latex_documents = [ ++ ('index', 'x86.tex', project, ++ 'The kernel development community', 'manual'), ++] +diff --git a/Documentation/x86/index.rst b/Documentation/x86/index.rst +new file mode 100644 +index 000000000000..ef389dcf1b1d +--- /dev/null ++++ b/Documentation/x86/index.rst +@@ -0,0 +1,8 @@ ++========================== ++x86 architecture specifics ++========================== ++ ++.. toctree:: ++ :maxdepth: 1 ++ ++ mds +diff --git a/Documentation/x86/mds.rst b/Documentation/x86/mds.rst +new file mode 100644 +index 000000000000..534e9baa4e1d +--- /dev/null ++++ b/Documentation/x86/mds.rst +@@ -0,0 +1,225 @@ ++Microarchitectural Data Sampling (MDS) mitigation ++================================================= ++ ++.. _mds: ++ ++Overview ++-------- ++ ++Microarchitectural Data Sampling (MDS) is a family of side channel attacks ++on internal buffers in Intel CPUs. The variants are: ++ ++ - Microarchitectural Store Buffer Data Sampling (MSBDS) (CVE-2018-12126) ++ - Microarchitectural Fill Buffer Data Sampling (MFBDS) (CVE-2018-12130) ++ - Microarchitectural Load Port Data Sampling (MLPDS) (CVE-2018-12127) ++ - Microarchitectural Data Sampling Uncacheable Memory (MDSUM) (CVE-2019-11091) ++ ++MSBDS leaks Store Buffer Entries which can be speculatively forwarded to a ++dependent load (store-to-load forwarding) as an optimization. The forward ++can also happen to a faulting or assisting load operation for a different ++memory address, which can be exploited under certain conditions. Store ++buffers are partitioned between Hyper-Threads so cross thread forwarding is ++not possible. But if a thread enters or exits a sleep state the store ++buffer is repartitioned which can expose data from one thread to the other. ++ ++MFBDS leaks Fill Buffer Entries. Fill buffers are used internally to manage ++L1 miss situations and to hold data which is returned or sent in response ++to a memory or I/O operation. Fill buffers can forward data to a load ++operation and also write data to the cache. When the fill buffer is ++deallocated it can retain the stale data of the preceding operations which ++can then be forwarded to a faulting or assisting load operation, which can ++be exploited under certain conditions. Fill buffers are shared between ++Hyper-Threads so cross thread leakage is possible. ++ ++MLPDS leaks Load Port Data. Load ports are used to perform load operations ++from memory or I/O. The received data is then forwarded to the register ++file or a subsequent operation. In some implementations the Load Port can ++contain stale data from a previous operation which can be forwarded to ++faulting or assisting loads under certain conditions, which again can be ++exploited eventually. Load ports are shared between Hyper-Threads so cross ++thread leakage is possible. ++ ++MDSUM is a special case of MSBDS, MFBDS and MLPDS. An uncacheable load from ++memory that takes a fault or assist can leave data in a microarchitectural ++structure that may later be observed using one of the same methods used by ++MSBDS, MFBDS or MLPDS. ++ ++Exposure assumptions ++-------------------- ++ ++It is assumed that attack code resides in user space or in a guest with one ++exception. The rationale behind this assumption is that the code construct ++needed for exploiting MDS requires: ++ ++ - to control the load to trigger a fault or assist ++ ++ - to have a disclosure gadget which exposes the speculatively accessed ++ data for consumption through a side channel. ++ ++ - to control the pointer through which the disclosure gadget exposes the ++ data ++ ++The existence of such a construct in the kernel cannot be excluded with ++100% certainty, but the complexity involved makes it extremly unlikely. ++ ++There is one exception, which is untrusted BPF. The functionality of ++untrusted BPF is limited, but it needs to be thoroughly investigated ++whether it can be used to create such a construct. ++ ++ ++Mitigation strategy ++------------------- ++ ++All variants have the same mitigation strategy at least for the single CPU ++thread case (SMT off): Force the CPU to clear the affected buffers. ++ ++This is achieved by using the otherwise unused and obsolete VERW ++instruction in combination with a microcode update. The microcode clears ++the affected CPU buffers when the VERW instruction is executed. ++ ++For virtualization there are two ways to achieve CPU buffer ++clearing. Either the modified VERW instruction or via the L1D Flush ++command. The latter is issued when L1TF mitigation is enabled so the extra ++VERW can be avoided. If the CPU is not affected by L1TF then VERW needs to ++be issued. ++ ++If the VERW instruction with the supplied segment selector argument is ++executed on a CPU without the microcode update there is no side effect ++other than a small number of pointlessly wasted CPU cycles. ++ ++This does not protect against cross Hyper-Thread attacks except for MSBDS ++which is only exploitable cross Hyper-thread when one of the Hyper-Threads ++enters a C-state. ++ ++The kernel provides a function to invoke the buffer clearing: ++ ++ mds_clear_cpu_buffers() ++ ++The mitigation is invoked on kernel/userspace, hypervisor/guest and C-state ++(idle) transitions. ++ ++As a special quirk to address virtualization scenarios where the host has ++the microcode updated, but the hypervisor does not (yet) expose the ++MD_CLEAR CPUID bit to guests, the kernel issues the VERW instruction in the ++hope that it might actually clear the buffers. The state is reflected ++accordingly. ++ ++According to current knowledge additional mitigations inside the kernel ++itself are not required because the necessary gadgets to expose the leaked ++data cannot be controlled in a way which allows exploitation from malicious ++user space or VM guests. ++ ++Kernel internal mitigation modes ++-------------------------------- ++ ++ ======= ============================================================ ++ off Mitigation is disabled. Either the CPU is not affected or ++ mds=off is supplied on the kernel command line ++ ++ full Mitigation is enabled. CPU is affected and MD_CLEAR is ++ advertised in CPUID. ++ ++ vmwerv Mitigation is enabled. CPU is affected and MD_CLEAR is not ++ advertised in CPUID. That is mainly for virtualization ++ scenarios where the host has the updated microcode but the ++ hypervisor does not expose MD_CLEAR in CPUID. It's a best ++ effort approach without guarantee. ++ ======= ============================================================ ++ ++If the CPU is affected and mds=off is not supplied on the kernel command ++line then the kernel selects the appropriate mitigation mode depending on ++the availability of the MD_CLEAR CPUID bit. ++ ++Mitigation points ++----------------- ++ ++1. Return to user space ++^^^^^^^^^^^^^^^^^^^^^^^ ++ ++ When transitioning from kernel to user space the CPU buffers are flushed ++ on affected CPUs when the mitigation is not disabled on the kernel ++ command line. The migitation is enabled through the static key ++ mds_user_clear. ++ ++ The mitigation is invoked in prepare_exit_to_usermode() which covers ++ most of the kernel to user space transitions. There are a few exceptions ++ which are not invoking prepare_exit_to_usermode() on return to user ++ space. These exceptions use the paranoid exit code. ++ ++ - Non Maskable Interrupt (NMI): ++ ++ Access to sensible data like keys, credentials in the NMI context is ++ mostly theoretical: The CPU can do prefetching or execute a ++ misspeculated code path and thereby fetching data which might end up ++ leaking through a buffer. ++ ++ But for mounting other attacks the kernel stack address of the task is ++ already valuable information. So in full mitigation mode, the NMI is ++ mitigated on the return from do_nmi() to provide almost complete ++ coverage. ++ ++ - Double fault (#DF): ++ ++ A double fault is usually fatal, but the ESPFIX workaround, which can ++ be triggered from user space through modify_ldt(2) is a recoverable ++ double fault. #DF uses the paranoid exit path, so explicit mitigation ++ in the double fault handler is required. ++ ++ - Machine Check Exception (#MC): ++ ++ Another corner case is a #MC which hits between the CPU buffer clear ++ invocation and the actual return to user. As this still is in kernel ++ space it takes the paranoid exit path which does not clear the CPU ++ buffers. So the #MC handler repopulates the buffers to some ++ extent. Machine checks are not reliably controllable and the window is ++ extremly small so mitigation would just tick a checkbox that this ++ theoretical corner case is covered. To keep the amount of special ++ cases small, ignore #MC. ++ ++ - Debug Exception (#DB): ++ ++ This takes the paranoid exit path only when the INT1 breakpoint is in ++ kernel space. #DB on a user space address takes the regular exit path, ++ so no extra mitigation required. ++ ++ ++2. C-State transition ++^^^^^^^^^^^^^^^^^^^^^ ++ ++ When a CPU goes idle and enters a C-State the CPU buffers need to be ++ cleared on affected CPUs when SMT is active. This addresses the ++ repartitioning of the store buffer when one of the Hyper-Threads enters ++ a C-State. ++ ++ When SMT is inactive, i.e. either the CPU does not support it or all ++ sibling threads are offline CPU buffer clearing is not required. ++ ++ The idle clearing is enabled on CPUs which are only affected by MSBDS ++ and not by any other MDS variant. The other MDS variants cannot be ++ protected against cross Hyper-Thread attacks because the Fill Buffer and ++ the Load Ports are shared. So on CPUs affected by other variants, the ++ idle clearing would be a window dressing exercise and is therefore not ++ activated. ++ ++ The invocation is controlled by the static key mds_idle_clear which is ++ switched depending on the chosen mitigation mode and the SMT state of ++ the system. ++ ++ The buffer clear is only invoked before entering the C-State to prevent ++ that stale data from the idling CPU from spilling to the Hyper-Thread ++ sibling after the store buffer got repartitioned and all entries are ++ available to the non idle sibling. ++ ++ When coming out of idle the store buffer is partitioned again so each ++ sibling has half of it available. The back from idle CPU could be then ++ speculatively exposed to contents of the sibling. The buffers are ++ flushed either on exit to user space or on VMENTER so malicious code ++ in user space or the guest cannot speculatively access them. ++ ++ The mitigation is hooked into all variants of halt()/mwait(), but does ++ not cover the legacy ACPI IO-Port mechanism because the ACPI idle driver ++ has been superseded by the intel_idle driver around 2010 and is ++ preferred on all affected CPUs which are expected to gain the MD_CLEAR ++ functionality in microcode. Aside of that the IO-Port mechanism is a ++ legacy interface which is only used on older systems which are either ++ not affected or do not receive microcode updates anymore. +diff --git a/Makefile b/Makefile +index 914d69b9e3fd..be894b3a97d5 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 4 + PATCHLEVEL = 19 +-SUBLEVEL = 42 ++SUBLEVEL = 43 + EXTRAVERSION = + NAME = "People's Front" + +diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c +index 1341325599a7..4ccbf611a3c5 100644 +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -56,7 +56,7 @@ void setup_barrier_nospec(void) + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && + security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR); + +- if (!no_nospec) ++ if (!no_nospec && !cpu_mitigations_off()) + enable_barrier_nospec(enable); + } + +@@ -115,7 +115,7 @@ static int __init handle_nospectre_v2(char *p) + early_param("nospectre_v2", handle_nospectre_v2); + void setup_spectre_v2(void) + { +- if (no_spectrev2) ++ if (no_spectrev2 || cpu_mitigations_off()) + do_btb_flush_fixups(); + else + btb_flush_enabled = true; +@@ -299,7 +299,7 @@ void setup_stf_barrier(void) + + stf_enabled_flush_types = type; + +- if (!no_stf_barrier) ++ if (!no_stf_barrier && !cpu_mitigations_off()) + stf_barrier_enable(enable); + } + +diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c +index faf00222b324..eaf7300be5ab 100644 +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -955,7 +955,7 @@ void setup_rfi_flush(enum l1d_flush_type types, bool enable) + + enabled_flush_types = types; + +- if (!no_rfi_flush) ++ if (!no_rfi_flush && !cpu_mitigations_off()) + rfi_flush_enable(enable); + } + +diff --git a/arch/s390/kernel/nospec-branch.c b/arch/s390/kernel/nospec-branch.c +index bdddaae96559..649135cbedd5 100644 +--- a/arch/s390/kernel/nospec-branch.c ++++ b/arch/s390/kernel/nospec-branch.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 + #include + #include ++#include + #include + + static int __init nobp_setup_early(char *str) +@@ -58,7 +59,7 @@ early_param("nospectre_v2", nospectre_v2_setup_early); + + void __init nospec_auto_detect(void) + { +- if (test_facility(156)) { ++ if (test_facility(156) || cpu_mitigations_off()) { + /* + * The machine supports etokens. + * Disable expolines and disable nobp. +diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c +index 3b2490b81918..8353348ddeaf 100644 +--- a/arch/x86/entry/common.c ++++ b/arch/x86/entry/common.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #define CREATE_TRACE_POINTS + #include +@@ -212,6 +213,8 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs) + #endif + + user_enter_irqoff(); ++ ++ mds_user_clear_cpu_buffers(); + } + + #define SYSCALL_EXIT_WORK_FLAGS \ +diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c +index f9958ad4d335..a759e59990fb 100644 +--- a/arch/x86/events/intel/core.c ++++ b/arch/x86/events/intel/core.c +@@ -4132,11 +4132,11 @@ __init int intel_pmu_init(void) + name = "nehalem"; + break; + +- case INTEL_FAM6_ATOM_PINEVIEW: +- case INTEL_FAM6_ATOM_LINCROFT: +- case INTEL_FAM6_ATOM_PENWELL: +- case INTEL_FAM6_ATOM_CLOVERVIEW: +- case INTEL_FAM6_ATOM_CEDARVIEW: ++ case INTEL_FAM6_ATOM_BONNELL: ++ case INTEL_FAM6_ATOM_BONNELL_MID: ++ case INTEL_FAM6_ATOM_SALTWELL: ++ case INTEL_FAM6_ATOM_SALTWELL_MID: ++ case INTEL_FAM6_ATOM_SALTWELL_TABLET: + memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, + sizeof(hw_cache_event_ids)); + +@@ -4149,9 +4149,11 @@ __init int intel_pmu_init(void) + name = "bonnell"; + break; + +- case INTEL_FAM6_ATOM_SILVERMONT1: +- case INTEL_FAM6_ATOM_SILVERMONT2: ++ case INTEL_FAM6_ATOM_SILVERMONT: ++ case INTEL_FAM6_ATOM_SILVERMONT_X: ++ case INTEL_FAM6_ATOM_SILVERMONT_MID: + case INTEL_FAM6_ATOM_AIRMONT: ++ case INTEL_FAM6_ATOM_AIRMONT_MID: + memcpy(hw_cache_event_ids, slm_hw_cache_event_ids, + sizeof(hw_cache_event_ids)); + memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs, +@@ -4170,7 +4172,7 @@ __init int intel_pmu_init(void) + break; + + case INTEL_FAM6_ATOM_GOLDMONT: +- case INTEL_FAM6_ATOM_DENVERTON: ++ case INTEL_FAM6_ATOM_GOLDMONT_X: + memcpy(hw_cache_event_ids, glm_hw_cache_event_ids, + sizeof(hw_cache_event_ids)); + memcpy(hw_cache_extra_regs, glm_hw_cache_extra_regs, +@@ -4196,7 +4198,7 @@ __init int intel_pmu_init(void) + name = "goldmont"; + break; + +- case INTEL_FAM6_ATOM_GEMINI_LAKE: ++ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: + memcpy(hw_cache_event_ids, glp_hw_cache_event_ids, + sizeof(hw_cache_event_ids)); + memcpy(hw_cache_extra_regs, glp_hw_cache_extra_regs, +diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c +index 6eb76106c469..56194c571299 100644 +--- a/arch/x86/events/intel/cstate.c ++++ b/arch/x86/events/intel/cstate.c +@@ -559,8 +559,8 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = { + + X86_CSTATES_MODEL(INTEL_FAM6_HASWELL_ULT, hswult_cstates), + +- X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT1, slm_cstates), +- X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT2, slm_cstates), ++ X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT, slm_cstates), ++ X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT_X, slm_cstates), + X86_CSTATES_MODEL(INTEL_FAM6_ATOM_AIRMONT, slm_cstates), + + X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL_CORE, snb_cstates), +@@ -581,9 +581,9 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = { + X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNM, knl_cstates), + + X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT, glm_cstates), +- X86_CSTATES_MODEL(INTEL_FAM6_ATOM_DENVERTON, glm_cstates), ++ X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT_X, glm_cstates), + +- X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GEMINI_LAKE, glm_cstates), ++ X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT_PLUS, glm_cstates), + { }, + }; + MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match); +diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c +index 32f3e9423e99..91039ffed633 100644 +--- a/arch/x86/events/intel/rapl.c ++++ b/arch/x86/events/intel/rapl.c +@@ -777,9 +777,9 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = { + X86_RAPL_MODEL_MATCH(INTEL_FAM6_CANNONLAKE_MOBILE, skl_rapl_init), + + X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT, hsw_rapl_init), +- X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_DENVERTON, hsw_rapl_init), ++ X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT_X, hsw_rapl_init), + +- X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GEMINI_LAKE, hsw_rapl_init), ++ X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT_PLUS, hsw_rapl_init), + {}, + }; + +diff --git a/arch/x86/events/msr.c b/arch/x86/events/msr.c +index b4771a6ddbc1..1b9f85abf9bc 100644 +--- a/arch/x86/events/msr.c ++++ b/arch/x86/events/msr.c +@@ -69,14 +69,14 @@ static bool test_intel(int idx) + case INTEL_FAM6_BROADWELL_GT3E: + case INTEL_FAM6_BROADWELL_X: + +- case INTEL_FAM6_ATOM_SILVERMONT1: +- case INTEL_FAM6_ATOM_SILVERMONT2: ++ case INTEL_FAM6_ATOM_SILVERMONT: ++ case INTEL_FAM6_ATOM_SILVERMONT_X: + case INTEL_FAM6_ATOM_AIRMONT: + + case INTEL_FAM6_ATOM_GOLDMONT: +- case INTEL_FAM6_ATOM_DENVERTON: ++ case INTEL_FAM6_ATOM_GOLDMONT_X: + +- case INTEL_FAM6_ATOM_GEMINI_LAKE: ++ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: + + case INTEL_FAM6_XEON_PHI_KNL: + case INTEL_FAM6_XEON_PHI_KNM: +diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h +index 7b31ee5223fc..69037da75ea0 100644 +--- a/arch/x86/include/asm/cpufeatures.h ++++ b/arch/x86/include/asm/cpufeatures.h +@@ -341,6 +341,7 @@ + #define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */ + #define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */ + #define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */ ++#define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */ + #define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ + #define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ + #define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ +@@ -378,5 +379,7 @@ + #define X86_BUG_SPECTRE_V2 X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */ + #define X86_BUG_SPEC_STORE_BYPASS X86_BUG(17) /* CPU is affected by speculative store bypass attack */ + #define X86_BUG_L1TF X86_BUG(18) /* CPU is affected by L1 Terminal Fault */ ++#define X86_BUG_MDS X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */ ++#define X86_BUG_MSBDS_ONLY X86_BUG(20) /* CPU is only affected by the MSDBS variant of BUG_MDS */ + + #endif /* _ASM_X86_CPUFEATURES_H */ +diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h +index 0ad25cc895ae..058b1a1994c4 100644 +--- a/arch/x86/include/asm/intel-family.h ++++ b/arch/x86/include/asm/intel-family.h +@@ -8,9 +8,6 @@ + * The "_X" parts are generally the EP and EX Xeons, or the + * "Extreme" ones, like Broadwell-E. + * +- * Things ending in "2" are usually because we have no better +- * name for them. There's no processor called "SILVERMONT2". +- * + * While adding a new CPUID for a new microarchitecture, add a new + * group to keep logically sorted out in chronological order. Within + * that group keep the CPUID for the variants sorted by model number. +@@ -59,19 +56,23 @@ + + /* "Small Core" Processors (Atom) */ + +-#define INTEL_FAM6_ATOM_PINEVIEW 0x1C +-#define INTEL_FAM6_ATOM_LINCROFT 0x26 +-#define INTEL_FAM6_ATOM_PENWELL 0x27 +-#define INTEL_FAM6_ATOM_CLOVERVIEW 0x35 +-#define INTEL_FAM6_ATOM_CEDARVIEW 0x36 +-#define INTEL_FAM6_ATOM_SILVERMONT1 0x37 /* BayTrail/BYT / Valleyview */ +-#define INTEL_FAM6_ATOM_SILVERMONT2 0x4D /* Avaton/Rangely */ +-#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* CherryTrail / Braswell */ +-#define INTEL_FAM6_ATOM_MERRIFIELD 0x4A /* Tangier */ +-#define INTEL_FAM6_ATOM_MOOREFIELD 0x5A /* Anniedale */ +-#define INTEL_FAM6_ATOM_GOLDMONT 0x5C +-#define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */ +-#define INTEL_FAM6_ATOM_GEMINI_LAKE 0x7A ++#define INTEL_FAM6_ATOM_BONNELL 0x1C /* Diamondville, Pineview */ ++#define INTEL_FAM6_ATOM_BONNELL_MID 0x26 /* Silverthorne, Lincroft */ ++ ++#define INTEL_FAM6_ATOM_SALTWELL 0x36 /* Cedarview */ ++#define INTEL_FAM6_ATOM_SALTWELL_MID 0x27 /* Penwell */ ++#define INTEL_FAM6_ATOM_SALTWELL_TABLET 0x35 /* Cloverview */ ++ ++#define INTEL_FAM6_ATOM_SILVERMONT 0x37 /* Bay Trail, Valleyview */ ++#define INTEL_FAM6_ATOM_SILVERMONT_X 0x4D /* Avaton, Rangely */ ++#define INTEL_FAM6_ATOM_SILVERMONT_MID 0x4A /* Merriefield */ ++ ++#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* Cherry Trail, Braswell */ ++#define INTEL_FAM6_ATOM_AIRMONT_MID 0x5A /* Moorefield */ ++ ++#define INTEL_FAM6_ATOM_GOLDMONT 0x5C /* Apollo Lake */ ++#define INTEL_FAM6_ATOM_GOLDMONT_X 0x5F /* Denverton */ ++#define INTEL_FAM6_ATOM_GOLDMONT_PLUS 0x7A /* Gemini Lake */ + + /* Xeon Phi */ + +diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h +index 15450a675031..c99c66b41e53 100644 +--- a/arch/x86/include/asm/irqflags.h ++++ b/arch/x86/include/asm/irqflags.h +@@ -6,6 +6,8 @@ + + #ifndef __ASSEMBLY__ + ++#include ++ + /* Provide __cpuidle; we can't safely include */ + #define __cpuidle __attribute__((__section__(".cpuidle.text"))) + +@@ -54,11 +56,13 @@ static inline void native_irq_enable(void) + + static inline __cpuidle void native_safe_halt(void) + { ++ mds_idle_clear_cpu_buffers(); + asm volatile("sti; hlt": : :"memory"); + } + + static inline __cpuidle void native_halt(void) + { ++ mds_idle_clear_cpu_buffers(); + asm volatile("hlt": : :"memory"); + } + +diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h +index f14ca0be1e3f..f85f43db9225 100644 +--- a/arch/x86/include/asm/msr-index.h ++++ b/arch/x86/include/asm/msr-index.h +@@ -2,6 +2,8 @@ + #ifndef _ASM_X86_MSR_INDEX_H + #define _ASM_X86_MSR_INDEX_H + ++#include ++ + /* + * CPU model specific register (MSR) numbers. + * +@@ -40,14 +42,14 @@ + /* Intel MSRs. Some also available on other CPUs */ + + #define MSR_IA32_SPEC_CTRL 0x00000048 /* Speculation Control */ +-#define SPEC_CTRL_IBRS (1 << 0) /* Indirect Branch Restricted Speculation */ ++#define SPEC_CTRL_IBRS BIT(0) /* Indirect Branch Restricted Speculation */ + #define SPEC_CTRL_STIBP_SHIFT 1 /* Single Thread Indirect Branch Predictor (STIBP) bit */ +-#define SPEC_CTRL_STIBP (1 << SPEC_CTRL_STIBP_SHIFT) /* STIBP mask */ ++#define SPEC_CTRL_STIBP BIT(SPEC_CTRL_STIBP_SHIFT) /* STIBP mask */ + #define SPEC_CTRL_SSBD_SHIFT 2 /* Speculative Store Bypass Disable bit */ +-#define SPEC_CTRL_SSBD (1 << SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */ ++#define SPEC_CTRL_SSBD BIT(SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */ + + #define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */ +-#define PRED_CMD_IBPB (1 << 0) /* Indirect Branch Prediction Barrier */ ++#define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */ + + #define MSR_PPIN_CTL 0x0000004e + #define MSR_PPIN 0x0000004f +@@ -69,20 +71,25 @@ + #define MSR_MTRRcap 0x000000fe + + #define MSR_IA32_ARCH_CAPABILITIES 0x0000010a +-#define ARCH_CAP_RDCL_NO (1 << 0) /* Not susceptible to Meltdown */ +-#define ARCH_CAP_IBRS_ALL (1 << 1) /* Enhanced IBRS support */ +-#define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH (1 << 3) /* Skip L1D flush on vmentry */ +-#define ARCH_CAP_SSB_NO (1 << 4) /* +- * Not susceptible to Speculative Store Bypass +- * attack, so no Speculative Store Bypass +- * control required. +- */ ++#define ARCH_CAP_RDCL_NO BIT(0) /* Not susceptible to Meltdown */ ++#define ARCH_CAP_IBRS_ALL BIT(1) /* Enhanced IBRS support */ ++#define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH BIT(3) /* Skip L1D flush on vmentry */ ++#define ARCH_CAP_SSB_NO BIT(4) /* ++ * Not susceptible to Speculative Store Bypass ++ * attack, so no Speculative Store Bypass ++ * control required. ++ */ ++#define ARCH_CAP_MDS_NO BIT(5) /* ++ * Not susceptible to ++ * Microarchitectural Data ++ * Sampling (MDS) vulnerabilities. ++ */ + + #define MSR_IA32_FLUSH_CMD 0x0000010b +-#define L1D_FLUSH (1 << 0) /* +- * Writeback and invalidate the +- * L1 data cache. +- */ ++#define L1D_FLUSH BIT(0) /* ++ * Writeback and invalidate the ++ * L1 data cache. ++ */ + + #define MSR_IA32_BBL_CR_CTL 0x00000119 + #define MSR_IA32_BBL_CR_CTL3 0x0000011e +diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h +index 39a2fb29378a..eb0f80ce8524 100644 +--- a/arch/x86/include/asm/mwait.h ++++ b/arch/x86/include/asm/mwait.h +@@ -6,6 +6,7 @@ + #include + + #include ++#include + + #define MWAIT_SUBSTATE_MASK 0xf + #define MWAIT_CSTATE_MASK 0xf +@@ -40,6 +41,8 @@ static inline void __monitorx(const void *eax, unsigned long ecx, + + static inline void __mwait(unsigned long eax, unsigned long ecx) + { ++ mds_idle_clear_cpu_buffers(); ++ + /* "mwait %eax, %ecx;" */ + asm volatile(".byte 0x0f, 0x01, 0xc9;" + :: "a" (eax), "c" (ecx)); +@@ -74,6 +77,8 @@ static inline void __mwait(unsigned long eax, unsigned long ecx) + static inline void __mwaitx(unsigned long eax, unsigned long ebx, + unsigned long ecx) + { ++ /* No MDS buffer clear as this is AMD/HYGON only */ ++ + /* "mwaitx %eax, %ebx, %ecx;" */ + asm volatile(".byte 0x0f, 0x01, 0xfb;" + :: "a" (eax), "b" (ebx), "c" (ecx)); +@@ -81,6 +86,8 @@ static inline void __mwaitx(unsigned long eax, unsigned long ebx, + + static inline void __sti_mwait(unsigned long eax, unsigned long ecx) + { ++ mds_idle_clear_cpu_buffers(); ++ + trace_hardirqs_on(); + /* "mwait %eax, %ecx;" */ + asm volatile("sti; .byte 0x0f, 0x01, 0xc9;" +diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h +index 032b6009baab..599c273f5d00 100644 +--- a/arch/x86/include/asm/nospec-branch.h ++++ b/arch/x86/include/asm/nospec-branch.h +@@ -317,6 +317,56 @@ DECLARE_STATIC_KEY_FALSE(switch_to_cond_stibp); + DECLARE_STATIC_KEY_FALSE(switch_mm_cond_ibpb); + DECLARE_STATIC_KEY_FALSE(switch_mm_always_ibpb); + ++DECLARE_STATIC_KEY_FALSE(mds_user_clear); ++DECLARE_STATIC_KEY_FALSE(mds_idle_clear); ++ ++#include ++ ++/** ++ * mds_clear_cpu_buffers - Mitigation for MDS vulnerability ++ * ++ * This uses the otherwise unused and obsolete VERW instruction in ++ * combination with microcode which triggers a CPU buffer flush when the ++ * instruction is executed. ++ */ ++static inline void mds_clear_cpu_buffers(void) ++{ ++ static const u16 ds = __KERNEL_DS; ++ ++ /* ++ * Has to be the memory-operand variant because only that ++ * guarantees the CPU buffer flush functionality according to ++ * documentation. The register-operand variant does not. ++ * Works with any segment selector, but a valid writable ++ * data segment is the fastest variant. ++ * ++ * "cc" clobber is required because VERW modifies ZF. ++ */ ++ asm volatile("verw %[ds]" : : [ds] "m" (ds) : "cc"); ++} ++ ++/** ++ * mds_user_clear_cpu_buffers - Mitigation for MDS vulnerability ++ * ++ * Clear CPU buffers if the corresponding static key is enabled ++ */ ++static inline void mds_user_clear_cpu_buffers(void) ++{ ++ if (static_branch_likely(&mds_user_clear)) ++ mds_clear_cpu_buffers(); ++} ++ ++/** ++ * mds_idle_clear_cpu_buffers - Mitigation for MDS vulnerability ++ * ++ * Clear CPU buffers if the corresponding static key is enabled ++ */ ++static inline void mds_idle_clear_cpu_buffers(void) ++{ ++ if (static_branch_likely(&mds_idle_clear)) ++ mds_clear_cpu_buffers(); ++} ++ + #endif /* __ASSEMBLY__ */ + + /* +diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h +index d53c54b842da..b54f25697beb 100644 +--- a/arch/x86/include/asm/processor.h ++++ b/arch/x86/include/asm/processor.h +@@ -997,4 +997,10 @@ enum l1tf_mitigations { + + extern enum l1tf_mitigations l1tf_mitigation; + ++enum mds_mitigations { ++ MDS_MITIGATION_OFF, ++ MDS_MITIGATION_FULL, ++ MDS_MITIGATION_VMWERV, ++}; ++ + #endif /* _ASM_X86_PROCESSOR_H */ +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index e5258bd64200..9b096f26d1c8 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -35,6 +35,7 @@ + static void __init spectre_v2_select_mitigation(void); + static void __init ssb_select_mitigation(void); + static void __init l1tf_select_mitigation(void); ++static void __init mds_select_mitigation(void); + + /* The base value of the SPEC_CTRL MSR that always has to be preserved. */ + u64 x86_spec_ctrl_base; +@@ -61,6 +62,13 @@ DEFINE_STATIC_KEY_FALSE(switch_mm_cond_ibpb); + /* Control unconditional IBPB in switch_mm() */ + DEFINE_STATIC_KEY_FALSE(switch_mm_always_ibpb); + ++/* Control MDS CPU buffer clear before returning to user space */ ++DEFINE_STATIC_KEY_FALSE(mds_user_clear); ++EXPORT_SYMBOL_GPL(mds_user_clear); ++/* Control MDS CPU buffer clear before idling (halt, mwait) */ ++DEFINE_STATIC_KEY_FALSE(mds_idle_clear); ++EXPORT_SYMBOL_GPL(mds_idle_clear); ++ + void __init check_bugs(void) + { + identify_boot_cpu(); +@@ -99,6 +107,10 @@ void __init check_bugs(void) + + l1tf_select_mitigation(); + ++ mds_select_mitigation(); ++ ++ arch_smt_update(); ++ + #ifdef CONFIG_X86_32 + /* + * Check whether we are able to run this kernel safely on SMP. +@@ -204,6 +216,61 @@ static void x86_amd_ssb_disable(void) + wrmsrl(MSR_AMD64_LS_CFG, msrval); + } + ++#undef pr_fmt ++#define pr_fmt(fmt) "MDS: " fmt ++ ++/* Default mitigation for MDS-affected CPUs */ ++static enum mds_mitigations mds_mitigation __ro_after_init = MDS_MITIGATION_FULL; ++static bool mds_nosmt __ro_after_init = false; ++ ++static const char * const mds_strings[] = { ++ [MDS_MITIGATION_OFF] = "Vulnerable", ++ [MDS_MITIGATION_FULL] = "Mitigation: Clear CPU buffers", ++ [MDS_MITIGATION_VMWERV] = "Vulnerable: Clear CPU buffers attempted, no microcode", ++}; ++ ++static void __init mds_select_mitigation(void) ++{ ++ if (!boot_cpu_has_bug(X86_BUG_MDS) || cpu_mitigations_off()) { ++ mds_mitigation = MDS_MITIGATION_OFF; ++ return; ++ } ++ ++ if (mds_mitigation == MDS_MITIGATION_FULL) { ++ if (!boot_cpu_has(X86_FEATURE_MD_CLEAR)) ++ mds_mitigation = MDS_MITIGATION_VMWERV; ++ ++ static_branch_enable(&mds_user_clear); ++ ++ if (!boot_cpu_has(X86_BUG_MSBDS_ONLY) && ++ (mds_nosmt || cpu_mitigations_auto_nosmt())) ++ cpu_smt_disable(false); ++ } ++ ++ pr_info("%s\n", mds_strings[mds_mitigation]); ++} ++ ++static int __init mds_cmdline(char *str) ++{ ++ if (!boot_cpu_has_bug(X86_BUG_MDS)) ++ return 0; ++ ++ if (!str) ++ return -EINVAL; ++ ++ if (!strcmp(str, "off")) ++ mds_mitigation = MDS_MITIGATION_OFF; ++ else if (!strcmp(str, "full")) ++ mds_mitigation = MDS_MITIGATION_FULL; ++ else if (!strcmp(str, "full,nosmt")) { ++ mds_mitigation = MDS_MITIGATION_FULL; ++ mds_nosmt = true; ++ } ++ ++ return 0; ++} ++early_param("mds", mds_cmdline); ++ + #undef pr_fmt + #define pr_fmt(fmt) "Spectre V2 : " fmt + +@@ -428,7 +495,8 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void) + char arg[20]; + int ret, i; + +- if (cmdline_find_option_bool(boot_command_line, "nospectre_v2")) ++ if (cmdline_find_option_bool(boot_command_line, "nospectre_v2") || ++ cpu_mitigations_off()) + return SPECTRE_V2_CMD_NONE; + + ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg)); +@@ -560,9 +628,6 @@ specv2_set_mode: + + /* Set up IBPB and STIBP depending on the general spectre V2 command */ + spectre_v2_user_select_mitigation(cmd); +- +- /* Enable STIBP if appropriate */ +- arch_smt_update(); + } + + static void update_stibp_msr(void * __unused) +@@ -596,6 +661,31 @@ static void update_indir_branch_cond(void) + static_branch_disable(&switch_to_cond_stibp); + } + ++#undef pr_fmt ++#define pr_fmt(fmt) fmt ++ ++/* Update the static key controlling the MDS CPU buffer clear in idle */ ++static void update_mds_branch_idle(void) ++{ ++ /* ++ * Enable the idle clearing if SMT is active on CPUs which are ++ * affected only by MSBDS and not any other MDS variant. ++ * ++ * The other variants cannot be mitigated when SMT is enabled, so ++ * clearing the buffers on idle just to prevent the Store Buffer ++ * repartitioning leak would be a window dressing exercise. ++ */ ++ if (!boot_cpu_has_bug(X86_BUG_MSBDS_ONLY)) ++ return; ++ ++ if (sched_smt_active()) ++ static_branch_enable(&mds_idle_clear); ++ else ++ static_branch_disable(&mds_idle_clear); ++} ++ ++#define MDS_MSG_SMT "MDS CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html for more details.\n" ++ + void arch_smt_update(void) + { + /* Enhanced IBRS implies STIBP. No update required. */ +@@ -616,6 +706,17 @@ void arch_smt_update(void) + break; + } + ++ switch (mds_mitigation) { ++ case MDS_MITIGATION_FULL: ++ case MDS_MITIGATION_VMWERV: ++ if (sched_smt_active() && !boot_cpu_has(X86_BUG_MSBDS_ONLY)) ++ pr_warn_once(MDS_MSG_SMT); ++ update_mds_branch_idle(); ++ break; ++ case MDS_MITIGATION_OFF: ++ break; ++ } ++ + mutex_unlock(&spec_ctrl_mutex); + } + +@@ -657,7 +758,8 @@ static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void) + char arg[20]; + int ret, i; + +- if (cmdline_find_option_bool(boot_command_line, "nospec_store_bypass_disable")) { ++ if (cmdline_find_option_bool(boot_command_line, "nospec_store_bypass_disable") || ++ cpu_mitigations_off()) { + return SPEC_STORE_BYPASS_CMD_NONE; + } else { + ret = cmdline_find_option(boot_command_line, "spec_store_bypass_disable", +@@ -978,6 +1080,11 @@ static void __init l1tf_select_mitigation(void) + if (!boot_cpu_has_bug(X86_BUG_L1TF)) + return; + ++ if (cpu_mitigations_off()) ++ l1tf_mitigation = L1TF_MITIGATION_OFF; ++ else if (cpu_mitigations_auto_nosmt()) ++ l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOSMT; ++ + override_cache_bits(&boot_cpu_data); + + switch (l1tf_mitigation) { +@@ -1006,7 +1113,7 @@ static void __init l1tf_select_mitigation(void) + pr_info("You may make it effective by booting the kernel with mem=%llu parameter.\n", + half_pa); + pr_info("However, doing so will make a part of your RAM unusable.\n"); +- pr_info("Reading https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html might help you decide.\n"); ++ pr_info("Reading https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html might help you decide.\n"); + return; + } + +@@ -1039,6 +1146,7 @@ static int __init l1tf_cmdline(char *str) + early_param("l1tf", l1tf_cmdline); + + #undef pr_fmt ++#define pr_fmt(fmt) fmt + + #ifdef CONFIG_SYSFS + +@@ -1077,6 +1185,23 @@ static ssize_t l1tf_show_state(char *buf) + } + #endif + ++static ssize_t mds_show_state(char *buf) ++{ ++ if (!hypervisor_is_type(X86_HYPER_NATIVE)) { ++ return sprintf(buf, "%s; SMT Host state unknown\n", ++ mds_strings[mds_mitigation]); ++ } ++ ++ if (boot_cpu_has(X86_BUG_MSBDS_ONLY)) { ++ return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation], ++ (mds_mitigation == MDS_MITIGATION_OFF ? "vulnerable" : ++ sched_smt_active() ? "mitigated" : "disabled")); ++ } ++ ++ return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation], ++ sched_smt_active() ? "vulnerable" : "disabled"); ++} ++ + static char *stibp_state(void) + { + if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED) +@@ -1141,6 +1266,10 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr + if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV)) + return l1tf_show_state(buf); + break; ++ ++ case X86_BUG_MDS: ++ return mds_show_state(buf); ++ + default: + break; + } +@@ -1172,4 +1301,9 @@ ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *b + { + return cpu_show_common(dev, attr, buf, X86_BUG_L1TF); + } ++ ++ssize_t cpu_show_mds(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ return cpu_show_common(dev, attr, buf, X86_BUG_MDS); ++} + #endif +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index 44c4ef3d989b..1073118b9bf0 100644 +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -948,60 +948,73 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c) + #endif + } + +-static const __initconst struct x86_cpu_id cpu_no_speculation[] = { +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CEDARVIEW, X86_FEATURE_ANY }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CLOVERVIEW, X86_FEATURE_ANY }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_LINCROFT, X86_FEATURE_ANY }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PENWELL, X86_FEATURE_ANY }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PINEVIEW, X86_FEATURE_ANY }, +- { X86_VENDOR_CENTAUR, 5 }, +- { X86_VENDOR_INTEL, 5 }, +- { X86_VENDOR_NSC, 5 }, +- { X86_VENDOR_ANY, 4 }, ++#define NO_SPECULATION BIT(0) ++#define NO_MELTDOWN BIT(1) ++#define NO_SSB BIT(2) ++#define NO_L1TF BIT(3) ++#define NO_MDS BIT(4) ++#define MSBDS_ONLY BIT(5) ++ ++#define VULNWL(_vendor, _family, _model, _whitelist) \ ++ { X86_VENDOR_##_vendor, _family, _model, X86_FEATURE_ANY, _whitelist } ++ ++#define VULNWL_INTEL(model, whitelist) \ ++ VULNWL(INTEL, 6, INTEL_FAM6_##model, whitelist) ++ ++#define VULNWL_AMD(family, whitelist) \ ++ VULNWL(AMD, family, X86_MODEL_ANY, whitelist) ++ ++static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = { ++ VULNWL(ANY, 4, X86_MODEL_ANY, NO_SPECULATION), ++ VULNWL(CENTAUR, 5, X86_MODEL_ANY, NO_SPECULATION), ++ VULNWL(INTEL, 5, X86_MODEL_ANY, NO_SPECULATION), ++ VULNWL(NSC, 5, X86_MODEL_ANY, NO_SPECULATION), ++ ++ /* Intel Family 6 */ ++ VULNWL_INTEL(ATOM_SALTWELL, NO_SPECULATION), ++ VULNWL_INTEL(ATOM_SALTWELL_TABLET, NO_SPECULATION), ++ VULNWL_INTEL(ATOM_SALTWELL_MID, NO_SPECULATION), ++ VULNWL_INTEL(ATOM_BONNELL, NO_SPECULATION), ++ VULNWL_INTEL(ATOM_BONNELL_MID, NO_SPECULATION), ++ ++ VULNWL_INTEL(ATOM_SILVERMONT, NO_SSB | NO_L1TF | MSBDS_ONLY), ++ VULNWL_INTEL(ATOM_SILVERMONT_X, NO_SSB | NO_L1TF | MSBDS_ONLY), ++ VULNWL_INTEL(ATOM_SILVERMONT_MID, NO_SSB | NO_L1TF | MSBDS_ONLY), ++ VULNWL_INTEL(ATOM_AIRMONT, NO_SSB | NO_L1TF | MSBDS_ONLY), ++ VULNWL_INTEL(XEON_PHI_KNL, NO_SSB | NO_L1TF | MSBDS_ONLY), ++ VULNWL_INTEL(XEON_PHI_KNM, NO_SSB | NO_L1TF | MSBDS_ONLY), ++ ++ VULNWL_INTEL(CORE_YONAH, NO_SSB), ++ ++ VULNWL_INTEL(ATOM_AIRMONT_MID, NO_L1TF | MSBDS_ONLY), ++ ++ VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF), ++ VULNWL_INTEL(ATOM_GOLDMONT_X, NO_MDS | NO_L1TF), ++ VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF), ++ ++ /* AMD Family 0xf - 0x12 */ ++ VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS), ++ VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS), ++ VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS), ++ VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS), ++ ++ /* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */ ++ VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS), + {} + }; + +-static const __initconst struct x86_cpu_id cpu_no_meltdown[] = { +- { X86_VENDOR_AMD }, +- {} +-}; +- +-/* Only list CPUs which speculate but are non susceptible to SSB */ +-static const __initconst struct x86_cpu_id cpu_no_spec_store_bypass[] = { +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT2 }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MERRIFIELD }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_CORE_YONAH }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM }, +- { X86_VENDOR_AMD, 0x12, }, +- { X86_VENDOR_AMD, 0x11, }, +- { X86_VENDOR_AMD, 0x10, }, +- { X86_VENDOR_AMD, 0xf, }, +- {} +-}; ++static bool __init cpu_matches(unsigned long which) ++{ ++ const struct x86_cpu_id *m = x86_match_cpu(cpu_vuln_whitelist); + +-static const __initconst struct x86_cpu_id cpu_no_l1tf[] = { +- /* in addition to cpu_no_speculation */ +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT2 }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MERRIFIELD }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MOOREFIELD }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_DENVERTON }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GEMINI_LAKE }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM }, +- {} +-}; ++ return m && !!(m->driver_data & which); ++} + + static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) + { + u64 ia32_cap = 0; + +- if (x86_match_cpu(cpu_no_speculation)) ++ if (cpu_matches(NO_SPECULATION)) + return; + + setup_force_cpu_bug(X86_BUG_SPECTRE_V1); +@@ -1010,15 +1023,20 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) + if (cpu_has(c, X86_FEATURE_ARCH_CAPABILITIES)) + rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap); + +- if (!x86_match_cpu(cpu_no_spec_store_bypass) && +- !(ia32_cap & ARCH_CAP_SSB_NO) && ++ if (!cpu_matches(NO_SSB) && !(ia32_cap & ARCH_CAP_SSB_NO) && + !cpu_has(c, X86_FEATURE_AMD_SSB_NO)) + setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS); + + if (ia32_cap & ARCH_CAP_IBRS_ALL) + setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED); + +- if (x86_match_cpu(cpu_no_meltdown)) ++ if (!cpu_matches(NO_MDS) && !(ia32_cap & ARCH_CAP_MDS_NO)) { ++ setup_force_cpu_bug(X86_BUG_MDS); ++ if (cpu_matches(MSBDS_ONLY)) ++ setup_force_cpu_bug(X86_BUG_MSBDS_ONLY); ++ } ++ ++ if (cpu_matches(NO_MELTDOWN)) + return; + + /* Rogue Data Cache Load? No! */ +@@ -1027,7 +1045,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) + + setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN); + +- if (x86_match_cpu(cpu_no_l1tf)) ++ if (cpu_matches(NO_L1TF)) + return; + + setup_force_cpu_bug(X86_BUG_L1TF); +diff --git a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c +index f8c260d522ca..912d53939f4f 100644 +--- a/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c ++++ b/arch/x86/kernel/cpu/intel_rdt_pseudo_lock.c +@@ -91,7 +91,7 @@ static u64 get_prefetch_disable_bits(void) + */ + return 0xF; + case INTEL_FAM6_ATOM_GOLDMONT: +- case INTEL_FAM6_ATOM_GEMINI_LAKE: ++ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: + /* + * SDM defines bits of MSR_MISC_FEATURE_CONTROL register + * as: +@@ -995,7 +995,7 @@ static int measure_cycles_perf_fn(void *_plr) + + switch (boot_cpu_data.x86_model) { + case INTEL_FAM6_ATOM_GOLDMONT: +- case INTEL_FAM6_ATOM_GEMINI_LAKE: ++ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: + l2_hit_bits = (0x52ULL << 16) | (0x2 << 8) | 0xd1; + l2_miss_bits = (0x52ULL << 16) | (0x10 << 8) | 0xd1; + break; +diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c +index 18bc9b51ac9b..086cf1d1d71d 100644 +--- a/arch/x86/kernel/nmi.c ++++ b/arch/x86/kernel/nmi.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + #define CREATE_TRACE_POINTS + #include +@@ -533,6 +534,9 @@ nmi_restart: + write_cr2(this_cpu_read(nmi_cr2)); + if (this_cpu_dec_return(nmi_state)) + goto nmi_restart; ++ ++ if (user_mode(regs)) ++ mds_user_clear_cpu_buffers(); + } + NOKPROBE_SYMBOL(do_nmi); + +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index e6db475164ed..0a5efd764914 100644 +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -387,6 +388,13 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) + regs->ip = (unsigned long)general_protection; + regs->sp = (unsigned long)&gpregs->orig_ax; + ++ /* ++ * This situation can be triggered by userspace via ++ * modify_ldt(2) and the return does not take the regular ++ * user space exit, so a CPU buffer clear is required when ++ * MDS mitigation is enabled. ++ */ ++ mds_user_clear_cpu_buffers(); + return; + } + #endif +diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c +index 6d5dc5dabfd7..03b7529333a6 100644 +--- a/arch/x86/kernel/tsc.c ++++ b/arch/x86/kernel/tsc.c +@@ -636,7 +636,7 @@ unsigned long native_calibrate_tsc(void) + case INTEL_FAM6_KABYLAKE_DESKTOP: + crystal_khz = 24000; /* 24.0 MHz */ + break; +- case INTEL_FAM6_ATOM_DENVERTON: ++ case INTEL_FAM6_ATOM_GOLDMONT_X: + crystal_khz = 25000; /* 25.0 MHz */ + break; + case INTEL_FAM6_ATOM_GOLDMONT: +diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c +index 27ef714d886c..3d0e9aeea7c8 100644 +--- a/arch/x86/kernel/tsc_msr.c ++++ b/arch/x86/kernel/tsc_msr.c +@@ -59,12 +59,12 @@ static const struct freq_desc freq_desc_ann = { + }; + + static const struct x86_cpu_id tsc_msr_cpu_ids[] = { +- INTEL_CPU_FAM6(ATOM_PENWELL, freq_desc_pnw), +- INTEL_CPU_FAM6(ATOM_CLOVERVIEW, freq_desc_clv), +- INTEL_CPU_FAM6(ATOM_SILVERMONT1, freq_desc_byt), ++ INTEL_CPU_FAM6(ATOM_SALTWELL_MID, freq_desc_pnw), ++ INTEL_CPU_FAM6(ATOM_SALTWELL_TABLET, freq_desc_clv), ++ INTEL_CPU_FAM6(ATOM_SILVERMONT, freq_desc_byt), ++ INTEL_CPU_FAM6(ATOM_SILVERMONT_MID, freq_desc_tng), + INTEL_CPU_FAM6(ATOM_AIRMONT, freq_desc_cht), +- INTEL_CPU_FAM6(ATOM_MERRIFIELD, freq_desc_tng), +- INTEL_CPU_FAM6(ATOM_MOOREFIELD, freq_desc_ann), ++ INTEL_CPU_FAM6(ATOM_AIRMONT_MID, freq_desc_ann), + {} + }; + +diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c +index 98d13c6a64be..b810102a9cfa 100644 +--- a/arch/x86/kvm/cpuid.c ++++ b/arch/x86/kvm/cpuid.c +@@ -382,7 +382,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, + /* cpuid 0x80000008.ebx */ + const u32 kvm_cpuid_8000_0008_ebx_x86_features = + F(AMD_IBPB) | F(AMD_IBRS) | F(AMD_SSBD) | F(VIRT_SSBD) | +- F(AMD_SSB_NO); ++ F(AMD_SSB_NO) | F(AMD_STIBP); + + /* cpuid 0xC0000001.edx */ + const u32 kvm_cpuid_C000_0001_edx_x86_features = +@@ -412,7 +412,8 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, + /* cpuid 7.0.edx*/ + const u32 kvm_cpuid_7_0_edx_x86_features = + F(AVX512_4VNNIW) | F(AVX512_4FMAPS) | F(SPEC_CTRL) | +- F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES); ++ F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES) | F(INTEL_STIBP) | ++ F(MD_CLEAR); + + /* all calls to cpuid_count() should be made on the same cpu */ + get_cpu(); +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 215339c7d161..73d6d585dd66 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -10765,8 +10765,11 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) + 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(); + + asm( + /* Store host registers */ +@@ -11127,8 +11130,8 @@ free_vcpu: + 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/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/l1tf.html for details.\n" ++#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) + { +diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c +index c1fc1ae6b429..4df3e5c89d57 100644 +--- a/arch/x86/mm/pti.c ++++ b/arch/x86/mm/pti.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -115,7 +116,8 @@ void __init pti_check_boottime_disable(void) + } + } + +- if (cmdline_find_option_bool(boot_command_line, "nopti")) { ++ if (cmdline_find_option_bool(boot_command_line, "nopti") || ++ cpu_mitigations_off()) { + pti_mode = PTI_FORCE_OFF; + pti_print_if_insecure("disabled on command line."); + return; +diff --git a/arch/x86/platform/atom/punit_atom_debug.c b/arch/x86/platform/atom/punit_atom_debug.c +index 034813d4ab1e..41dae0f0d898 100644 +--- a/arch/x86/platform/atom/punit_atom_debug.c ++++ b/arch/x86/platform/atom/punit_atom_debug.c +@@ -143,8 +143,8 @@ static void punit_dbgfs_unregister(void) + (kernel_ulong_t)&drv_data } + + static const struct x86_cpu_id intel_punit_cpu_ids[] = { +- ICPU(INTEL_FAM6_ATOM_SILVERMONT1, punit_device_byt), +- ICPU(INTEL_FAM6_ATOM_MERRIFIELD, punit_device_tng), ++ ICPU(INTEL_FAM6_ATOM_SILVERMONT, punit_device_byt), ++ ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID, punit_device_tng), + ICPU(INTEL_FAM6_ATOM_AIRMONT, punit_device_cht), + {} + }; +diff --git a/arch/x86/platform/intel-mid/device_libs/platform_bt.c b/arch/x86/platform/intel-mid/device_libs/platform_bt.c +index 5a0483e7bf66..31dce781364c 100644 +--- a/arch/x86/platform/intel-mid/device_libs/platform_bt.c ++++ b/arch/x86/platform/intel-mid/device_libs/platform_bt.c +@@ -68,7 +68,7 @@ static struct bt_sfi_data tng_bt_sfi_data __initdata = { + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (kernel_ulong_t)&ddata } + + static const struct x86_cpu_id bt_sfi_cpu_ids[] = { +- ICPU(INTEL_FAM6_ATOM_MERRIFIELD, tng_bt_sfi_data), ++ ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID, tng_bt_sfi_data), + {} + }; + +diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c +index 969bf8d515c0..c651e206d796 100644 +--- a/drivers/acpi/acpi_lpss.c ++++ b/drivers/acpi/acpi_lpss.c +@@ -292,7 +292,7 @@ static const struct lpss_device_desc bsw_spi_dev_desc = { + #define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, } + + static const struct x86_cpu_id lpss_cpu_ids[] = { +- ICPU(INTEL_FAM6_ATOM_SILVERMONT1), /* Valleyview, Bay Trail */ ++ ICPU(INTEL_FAM6_ATOM_SILVERMONT), /* Valleyview, Bay Trail */ + ICPU(INTEL_FAM6_ATOM_AIRMONT), /* Braswell, Cherry Trail */ + {} + }; +diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c +index 06c31ec3cc70..9a8e286dd86f 100644 +--- a/drivers/acpi/x86/utils.c ++++ b/drivers/acpi/x86/utils.c +@@ -54,7 +54,7 @@ static const struct always_present_id always_present_ids[] = { + * Bay / Cherry Trail PWM directly poked by GPU driver in win10, + * but Linux uses a separate PWM driver, harmless if not used. + */ +- ENTRY("80860F09", "1", ICPU(INTEL_FAM6_ATOM_SILVERMONT1), {}), ++ ENTRY("80860F09", "1", ICPU(INTEL_FAM6_ATOM_SILVERMONT), {}), + ENTRY("80862288", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {}), + /* + * The INT0002 device is necessary to clear wakeup interrupt sources +diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c +index eb9443d5bae1..2fd6ca1021c2 100644 +--- a/drivers/base/cpu.c ++++ b/drivers/base/cpu.c +@@ -546,11 +546,18 @@ ssize_t __weak cpu_show_l1tf(struct device *dev, + return sprintf(buf, "Not affected\n"); + } + ++ssize_t __weak cpu_show_mds(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "Not affected\n"); ++} ++ + static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL); + static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL); + static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL); + static DEVICE_ATTR(spec_store_bypass, 0444, cpu_show_spec_store_bypass, NULL); + static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL); ++static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL); + + static struct attribute *cpu_root_vulnerabilities_attrs[] = { + &dev_attr_meltdown.attr, +@@ -558,6 +565,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = { + &dev_attr_spectre_v2.attr, + &dev_attr_spec_store_bypass.attr, + &dev_attr_l1tf.attr, ++ &dev_attr_mds.attr, + NULL + }; + +diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c +index a005711f909e..29f25d5d65e0 100644 +--- a/drivers/cpufreq/intel_pstate.c ++++ b/drivers/cpufreq/intel_pstate.c +@@ -1779,7 +1779,7 @@ static const struct pstate_funcs knl_funcs = { + static const struct x86_cpu_id intel_pstate_cpu_ids[] = { + ICPU(INTEL_FAM6_SANDYBRIDGE, core_funcs), + ICPU(INTEL_FAM6_SANDYBRIDGE_X, core_funcs), +- ICPU(INTEL_FAM6_ATOM_SILVERMONT1, silvermont_funcs), ++ ICPU(INTEL_FAM6_ATOM_SILVERMONT, silvermont_funcs), + ICPU(INTEL_FAM6_IVYBRIDGE, core_funcs), + ICPU(INTEL_FAM6_HASWELL_CORE, core_funcs), + ICPU(INTEL_FAM6_BROADWELL_CORE, core_funcs), +@@ -1796,7 +1796,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = { + ICPU(INTEL_FAM6_XEON_PHI_KNL, knl_funcs), + ICPU(INTEL_FAM6_XEON_PHI_KNM, knl_funcs), + ICPU(INTEL_FAM6_ATOM_GOLDMONT, core_funcs), +- ICPU(INTEL_FAM6_ATOM_GEMINI_LAKE, core_funcs), ++ ICPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, core_funcs), + ICPU(INTEL_FAM6_SKYLAKE_X, core_funcs), + {} + }; +diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c +index df28b65358d2..903a4f1fadcc 100644 +--- a/drivers/edac/pnd2_edac.c ++++ b/drivers/edac/pnd2_edac.c +@@ -1541,7 +1541,7 @@ static struct dunit_ops dnv_ops = { + + static const struct x86_cpu_id pnd2_cpuids[] = { + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT, 0, (kernel_ulong_t)&apl_ops }, +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_DENVERTON, 0, (kernel_ulong_t)&dnv_ops }, ++ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT_X, 0, (kernel_ulong_t)&dnv_ops }, + { } + }; + MODULE_DEVICE_TABLE(x86cpu, pnd2_cpuids); +diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c +index b2ccce5fb071..c4bb67ed8da3 100644 +--- a/drivers/idle/intel_idle.c ++++ b/drivers/idle/intel_idle.c +@@ -1076,14 +1076,14 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { + ICPU(INTEL_FAM6_WESTMERE, idle_cpu_nehalem), + ICPU(INTEL_FAM6_WESTMERE_EP, idle_cpu_nehalem), + ICPU(INTEL_FAM6_NEHALEM_EX, idle_cpu_nehalem), +- ICPU(INTEL_FAM6_ATOM_PINEVIEW, idle_cpu_atom), +- ICPU(INTEL_FAM6_ATOM_LINCROFT, idle_cpu_lincroft), ++ ICPU(INTEL_FAM6_ATOM_BONNELL, idle_cpu_atom), ++ ICPU(INTEL_FAM6_ATOM_BONNELL_MID, idle_cpu_lincroft), + ICPU(INTEL_FAM6_WESTMERE_EX, idle_cpu_nehalem), + ICPU(INTEL_FAM6_SANDYBRIDGE, idle_cpu_snb), + ICPU(INTEL_FAM6_SANDYBRIDGE_X, idle_cpu_snb), +- ICPU(INTEL_FAM6_ATOM_CEDARVIEW, idle_cpu_atom), +- ICPU(INTEL_FAM6_ATOM_SILVERMONT1, idle_cpu_byt), +- ICPU(INTEL_FAM6_ATOM_MERRIFIELD, idle_cpu_tangier), ++ ICPU(INTEL_FAM6_ATOM_SALTWELL, idle_cpu_atom), ++ ICPU(INTEL_FAM6_ATOM_SILVERMONT, idle_cpu_byt), ++ ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID, idle_cpu_tangier), + ICPU(INTEL_FAM6_ATOM_AIRMONT, idle_cpu_cht), + ICPU(INTEL_FAM6_IVYBRIDGE, idle_cpu_ivb), + ICPU(INTEL_FAM6_IVYBRIDGE_X, idle_cpu_ivt), +@@ -1091,7 +1091,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { + ICPU(INTEL_FAM6_HASWELL_X, idle_cpu_hsw), + ICPU(INTEL_FAM6_HASWELL_ULT, idle_cpu_hsw), + ICPU(INTEL_FAM6_HASWELL_GT3E, idle_cpu_hsw), +- ICPU(INTEL_FAM6_ATOM_SILVERMONT2, idle_cpu_avn), ++ ICPU(INTEL_FAM6_ATOM_SILVERMONT_X, idle_cpu_avn), + ICPU(INTEL_FAM6_BROADWELL_CORE, idle_cpu_bdw), + ICPU(INTEL_FAM6_BROADWELL_GT3E, idle_cpu_bdw), + ICPU(INTEL_FAM6_BROADWELL_X, idle_cpu_bdw), +@@ -1104,8 +1104,8 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { + ICPU(INTEL_FAM6_XEON_PHI_KNL, idle_cpu_knl), + ICPU(INTEL_FAM6_XEON_PHI_KNM, idle_cpu_knl), + ICPU(INTEL_FAM6_ATOM_GOLDMONT, idle_cpu_bxt), +- ICPU(INTEL_FAM6_ATOM_GEMINI_LAKE, idle_cpu_bxt), +- ICPU(INTEL_FAM6_ATOM_DENVERTON, idle_cpu_dnv), ++ ICPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, idle_cpu_bxt), ++ ICPU(INTEL_FAM6_ATOM_GOLDMONT_X, idle_cpu_dnv), + {} + }; + +@@ -1322,7 +1322,7 @@ static void intel_idle_state_table_update(void) + ivt_idle_state_table_update(); + break; + case INTEL_FAM6_ATOM_GOLDMONT: +- case INTEL_FAM6_ATOM_GEMINI_LAKE: ++ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: + bxt_idle_state_table_update(); + break; + case INTEL_FAM6_SKYLAKE_DESKTOP: +diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c +index c61109f7b793..57c1ec322e42 100644 +--- a/drivers/mmc/host/sdhci-acpi.c ++++ b/drivers/mmc/host/sdhci-acpi.c +@@ -247,7 +247,7 @@ static const struct sdhci_acpi_chip sdhci_acpi_chip_int = { + static bool sdhci_acpi_byt(void) + { + static const struct x86_cpu_id byt[] = { +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 }, ++ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, + {} + }; + +diff --git a/drivers/pci/pci-mid.c b/drivers/pci/pci-mid.c +index 314e135014dc..30fbe2ea6eab 100644 +--- a/drivers/pci/pci-mid.c ++++ b/drivers/pci/pci-mid.c +@@ -62,8 +62,8 @@ static const struct pci_platform_pm_ops mid_pci_platform_pm = { + * arch/x86/platform/intel-mid/pwr.c. + */ + static const struct x86_cpu_id lpss_cpu_ids[] = { +- ICPU(INTEL_FAM6_ATOM_PENWELL), +- ICPU(INTEL_FAM6_ATOM_MERRIFIELD), ++ ICPU(INTEL_FAM6_ATOM_SALTWELL_MID), ++ ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID), + {} + }; + +diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel_int0002_vgpio.c +index a473dc51b18d..e89ad4964dc1 100644 +--- a/drivers/platform/x86/intel_int0002_vgpio.c ++++ b/drivers/platform/x86/intel_int0002_vgpio.c +@@ -60,7 +60,7 @@ static const struct x86_cpu_id int0002_cpu_ids[] = { + /* + * Limit ourselves to Cherry Trail for now, until testing shows we + * need to handle the INT0002 device on Baytrail too. +- * ICPU(INTEL_FAM6_ATOM_SILVERMONT1), * Valleyview, Bay Trail * ++ * ICPU(INTEL_FAM6_ATOM_SILVERMONT), * Valleyview, Bay Trail * + */ + ICPU(INTEL_FAM6_ATOM_AIRMONT), /* Braswell, Cherry Trail */ + {} +diff --git a/drivers/platform/x86/intel_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c +index d79fbf924b13..5ad44204a9c3 100644 +--- a/drivers/platform/x86/intel_mid_powerbtn.c ++++ b/drivers/platform/x86/intel_mid_powerbtn.c +@@ -125,8 +125,8 @@ static const struct mid_pb_ddata mrfld_ddata = { + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (kernel_ulong_t)&ddata } + + static const struct x86_cpu_id mid_pb_cpu_ids[] = { +- ICPU(INTEL_FAM6_ATOM_PENWELL, mfld_ddata), +- ICPU(INTEL_FAM6_ATOM_MERRIFIELD, mrfld_ddata), ++ ICPU(INTEL_FAM6_ATOM_SALTWELL_MID, mfld_ddata), ++ ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID, mrfld_ddata), + {} + }; + +diff --git a/drivers/platform/x86/intel_telemetry_debugfs.c b/drivers/platform/x86/intel_telemetry_debugfs.c +index 1423fa8710fd..b998d7da97fb 100644 +--- a/drivers/platform/x86/intel_telemetry_debugfs.c ++++ b/drivers/platform/x86/intel_telemetry_debugfs.c +@@ -320,7 +320,7 @@ static struct telemetry_debugfs_conf telem_apl_debugfs_conf = { + + static const struct x86_cpu_id telemetry_debugfs_cpu_ids[] = { + TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GOLDMONT, telem_apl_debugfs_conf), +- TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GEMINI_LAKE, telem_apl_debugfs_conf), ++ TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, telem_apl_debugfs_conf), + {} + }; + +diff --git a/drivers/platform/x86/intel_telemetry_pltdrv.c b/drivers/platform/x86/intel_telemetry_pltdrv.c +index 2f889d6c270e..fcc6bee51a42 100644 +--- a/drivers/platform/x86/intel_telemetry_pltdrv.c ++++ b/drivers/platform/x86/intel_telemetry_pltdrv.c +@@ -192,7 +192,7 @@ static struct telemetry_plt_config telem_glk_config = { + + static const struct x86_cpu_id telemetry_cpu_ids[] = { + TELEM_CPU(INTEL_FAM6_ATOM_GOLDMONT, telem_apl_config), +- TELEM_CPU(INTEL_FAM6_ATOM_GEMINI_LAKE, telem_glk_config), ++ TELEM_CPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, telem_glk_config), + {} + }; + +diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c +index 295d8dcba48c..8cbfcce57a06 100644 +--- a/drivers/powercap/intel_rapl.c ++++ b/drivers/powercap/intel_rapl.c +@@ -1164,13 +1164,13 @@ static const struct x86_cpu_id rapl_ids[] __initconst = { + RAPL_CPU(INTEL_FAM6_KABYLAKE_DESKTOP, rapl_defaults_core), + RAPL_CPU(INTEL_FAM6_CANNONLAKE_MOBILE, rapl_defaults_core), + +- RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT1, rapl_defaults_byt), ++ RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT, rapl_defaults_byt), + RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT, rapl_defaults_cht), +- RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD, rapl_defaults_tng), +- RAPL_CPU(INTEL_FAM6_ATOM_MOOREFIELD, rapl_defaults_ann), ++ RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT_MID, rapl_defaults_tng), ++ RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT_MID, rapl_defaults_ann), + RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT, rapl_defaults_core), +- RAPL_CPU(INTEL_FAM6_ATOM_GEMINI_LAKE, rapl_defaults_core), +- RAPL_CPU(INTEL_FAM6_ATOM_DENVERTON, rapl_defaults_core), ++ RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, rapl_defaults_core), ++ RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT_X, rapl_defaults_core), + + RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL, rapl_defaults_hsw_server), + RAPL_CPU(INTEL_FAM6_XEON_PHI_KNM, rapl_defaults_hsw_server), +diff --git a/drivers/thermal/intel_soc_dts_thermal.c b/drivers/thermal/intel_soc_dts_thermal.c +index 1e47511a6bd5..d748527d7a38 100644 +--- a/drivers/thermal/intel_soc_dts_thermal.c ++++ b/drivers/thermal/intel_soc_dts_thermal.c +@@ -45,7 +45,7 @@ static irqreturn_t soc_irq_thread_fn(int irq, void *dev_data) + } + + static const struct x86_cpu_id soc_thermal_ids[] = { +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1, 0, ++ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT, 0, + BYT_SOC_DTS_APIC_IRQ}, + {} + }; +diff --git a/include/linux/cpu.h b/include/linux/cpu.h +index 5041357d0297..57ae83c4d5f4 100644 +--- a/include/linux/cpu.h ++++ b/include/linux/cpu.h +@@ -57,6 +57,8 @@ extern ssize_t cpu_show_spec_store_bypass(struct device *dev, + struct device_attribute *attr, char *buf); + extern ssize_t cpu_show_l1tf(struct device *dev, + struct device_attribute *attr, char *buf); ++extern ssize_t cpu_show_mds(struct device *dev, ++ struct device_attribute *attr, char *buf); + + extern __printf(4, 5) + struct device *cpu_device_create(struct device *parent, void *drvdata, +@@ -187,4 +189,28 @@ static inline void cpu_smt_disable(bool force) { } + static inline void cpu_smt_check_topology(void) { } + #endif + ++/* ++ * These are used for a global "mitigations=" cmdline option for toggling ++ * optional CPU mitigations. ++ */ ++enum cpu_mitigations { ++ CPU_MITIGATIONS_OFF, ++ CPU_MITIGATIONS_AUTO, ++ CPU_MITIGATIONS_AUTO_NOSMT, ++}; ++ ++extern enum cpu_mitigations cpu_mitigations; ++ ++/* mitigations=off */ ++static inline bool cpu_mitigations_off(void) ++{ ++ return cpu_mitigations == CPU_MITIGATIONS_OFF; ++} ++ ++/* mitigations=auto,nosmt */ ++static inline bool cpu_mitigations_auto_nosmt(void) ++{ ++ return cpu_mitigations == CPU_MITIGATIONS_AUTO_NOSMT; ++} ++ + #endif /* _LINUX_CPU_H_ */ +diff --git a/kernel/cpu.c b/kernel/cpu.c +index dc250ec2c096..bc6c880a093f 100644 +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -2278,3 +2278,18 @@ void __init boot_cpu_hotplug_init(void) + #endif + this_cpu_write(cpuhp_state.state, CPUHP_ONLINE); + } ++ ++enum cpu_mitigations cpu_mitigations __ro_after_init = CPU_MITIGATIONS_AUTO; ++ ++static int __init mitigations_parse_cmdline(char *arg) ++{ ++ if (!strcmp(arg, "off")) ++ cpu_mitigations = CPU_MITIGATIONS_OFF; ++ else if (!strcmp(arg, "auto")) ++ cpu_mitigations = CPU_MITIGATIONS_AUTO; ++ else if (!strcmp(arg, "auto,nosmt")) ++ cpu_mitigations = CPU_MITIGATIONS_AUTO_NOSMT; ++ ++ return 0; ++} ++early_param("mitigations", mitigations_parse_cmdline); +diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c +index b74bbee111c6..c6c8d20be1d2 100644 +--- a/sound/soc/intel/boards/bytcr_rt5651.c ++++ b/sound/soc/intel/boards/bytcr_rt5651.c +@@ -787,7 +787,7 @@ static struct snd_soc_card byt_rt5651_card = { + }; + + static const struct x86_cpu_id baytrail_cpu_ids[] = { +- { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 }, /* Valleyview */ ++ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, /* Valleyview */ + {} + }; + +diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile +index 2ab25aa38263..ff058bfbca3e 100644 +--- a/tools/power/x86/turbostat/Makefile ++++ b/tools/power/x86/turbostat/Makefile +@@ -9,7 +9,7 @@ ifeq ("$(origin O)", "command line") + endif + + turbostat : turbostat.c +-CFLAGS += -Wall ++CFLAGS += -Wall -I../../../include + CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"' + CFLAGS += -DINTEL_FAMILY_HEADER='"../../../../arch/x86/include/asm/intel-family.h"' + +diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c +index 83964f796edb..fbb53c952b73 100644 +--- a/tools/power/x86/turbostat/turbostat.c ++++ b/tools/power/x86/turbostat/turbostat.c +@@ -2082,7 +2082,7 @@ int has_turbo_ratio_group_limits(int family, int model) + switch (model) { + case INTEL_FAM6_ATOM_GOLDMONT: + case INTEL_FAM6_SKYLAKE_X: +- case INTEL_FAM6_ATOM_DENVERTON: ++ case INTEL_FAM6_ATOM_GOLDMONT_X: + return 1; + } + return 0; +@@ -3149,9 +3149,9 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) + pkg_cstate_limits = skx_pkg_cstate_limits; + has_misc_feature_control = 1; + break; +- case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ ++ case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ + no_MSR_MISC_PWR_MGMT = 1; +- case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ ++ case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */ + pkg_cstate_limits = slv_pkg_cstate_limits; + break; + case INTEL_FAM6_ATOM_AIRMONT: /* AMT */ +@@ -3163,8 +3163,8 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) + pkg_cstate_limits = phi_pkg_cstate_limits; + break; + case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ +- case INTEL_FAM6_ATOM_GEMINI_LAKE: +- case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ ++ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: ++ case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */ + pkg_cstate_limits = bxt_pkg_cstate_limits; + break; + default: +@@ -3193,9 +3193,9 @@ int has_slv_msrs(unsigned int family, unsigned int model) + return 0; + + switch (model) { +- case INTEL_FAM6_ATOM_SILVERMONT1: +- case INTEL_FAM6_ATOM_MERRIFIELD: +- case INTEL_FAM6_ATOM_MOOREFIELD: ++ case INTEL_FAM6_ATOM_SILVERMONT: ++ case INTEL_FAM6_ATOM_SILVERMONT_MID: ++ case INTEL_FAM6_ATOM_AIRMONT_MID: + return 1; + } + return 0; +@@ -3207,7 +3207,7 @@ int is_dnv(unsigned int family, unsigned int model) + return 0; + + switch (model) { +- case INTEL_FAM6_ATOM_DENVERTON: ++ case INTEL_FAM6_ATOM_GOLDMONT_X: + return 1; + } + return 0; +@@ -3724,8 +3724,8 @@ double get_tdp(unsigned int model) + return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units; + + switch (model) { +- case INTEL_FAM6_ATOM_SILVERMONT1: +- case INTEL_FAM6_ATOM_SILVERMONT2: ++ case INTEL_FAM6_ATOM_SILVERMONT: ++ case INTEL_FAM6_ATOM_SILVERMONT_X: + return 30.0; + default: + return 135.0; +@@ -3791,7 +3791,7 @@ void rapl_probe(unsigned int family, unsigned int model) + } + break; + case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ +- case INTEL_FAM6_ATOM_GEMINI_LAKE: ++ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: + do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO; + if (rapl_joules) + BIC_PRESENT(BIC_Pkg_J); +@@ -3850,8 +3850,8 @@ void rapl_probe(unsigned int family, unsigned int model) + BIC_PRESENT(BIC_RAMWatt); + } + break; +- case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ +- case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ ++ case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ ++ case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */ + do_rapl = RAPL_PKG | RAPL_CORES; + if (rapl_joules) { + BIC_PRESENT(BIC_Pkg_J); +@@ -3861,7 +3861,7 @@ void rapl_probe(unsigned int family, unsigned int model) + BIC_PRESENT(BIC_CorWatt); + } + break; +- case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ ++ case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */ + do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS; + BIC_PRESENT(BIC_PKG__); + BIC_PRESENT(BIC_RAM__); +@@ -3884,7 +3884,7 @@ void rapl_probe(unsigned int family, unsigned int model) + return; + + rapl_power_units = 1.0 / (1 << (msr & 0xF)); +- if (model == INTEL_FAM6_ATOM_SILVERMONT1) ++ if (model == INTEL_FAM6_ATOM_SILVERMONT) + rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000; + else + rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F)); +@@ -4141,8 +4141,8 @@ int has_snb_msrs(unsigned int family, unsigned int model) + case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */ + case INTEL_FAM6_SKYLAKE_X: /* SKX */ + case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ +- case INTEL_FAM6_ATOM_GEMINI_LAKE: +- case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ ++ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: ++ case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */ + return 1; + } + return 0; +@@ -4174,7 +4174,7 @@ int has_hsw_msrs(unsigned int family, unsigned int model) + case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ + case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */ + case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ +- case INTEL_FAM6_ATOM_GEMINI_LAKE: ++ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: + return 1; + } + return 0; +@@ -4209,8 +4209,8 @@ int is_slm(unsigned int family, unsigned int model) + if (!genuine_intel) + return 0; + switch (model) { +- case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ +- case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ ++ case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ ++ case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */ + return 1; + } + return 0; +@@ -4581,11 +4581,11 @@ void process_cpuid() + case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ + crystal_hz = 24000000; /* 24.0 MHz */ + break; +- case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ ++ case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */ + crystal_hz = 25000000; /* 25.0 MHz */ + break; + case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ +- case INTEL_FAM6_ATOM_GEMINI_LAKE: ++ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: + crystal_hz = 19200000; /* 19.2 MHz */ + break; + default: +diff --git a/tools/power/x86/x86_energy_perf_policy/Makefile b/tools/power/x86/x86_energy_perf_policy/Makefile +index f4534fb8b951..da781b430937 100644 +--- a/tools/power/x86/x86_energy_perf_policy/Makefile ++++ b/tools/power/x86/x86_energy_perf_policy/Makefile +@@ -9,7 +9,7 @@ ifeq ("$(origin O)", "command line") + endif + + x86_energy_perf_policy : x86_energy_perf_policy.c +-CFLAGS += -Wall ++CFLAGS += -Wall -I../../../include + CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"' + + %: %.c diff --git a/patch/kernel/sunxi-next/xxx-opi-win-bluetooth.patch b/patch/kernel/sunxi-next/xxx-opi-win-bluetooth.patch new file mode 100644 index 0000000000..a77db4f074 --- /dev/null +++ b/patch/kernel/sunxi-next/xxx-opi-win-bluetooth.patch @@ -0,0 +1,56 @@ +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts +index b4ce2e056..63b9e7433 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts +@@ -94,6 +94,8 @@ + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&r_pio 0 8 GPIO_ACTIVE_LOW>; /* PL8 */ ++ clocks = <&rtc 1>; ++ clock-names = "ext_clock"; + }; + + hdmi-connector { +@@ -191,6 +193,14 @@ + bus-width = <4>; + non-removable; + status = "okay"; ++ ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ interrupt-parent = <&r_pio>; ++ interrupts = <0 7 IRQ_TYPE_LEVEL_LOW>; /* PL7 */ ++ interrupt-names = "host-wake"; ++ }; + }; + + &ohci0 { +@@ -363,7 +373,20 @@ + &uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; ++ uart-has-rtscts; + status = "okay"; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ max-speed = <1500000>; ++ clocks = <&rtc 1>; ++ clock-names = "lpo"; ++ vbat-supply = <®_dldo2>; ++ vddio-supply = <®_dldo4>; ++ device-wakeup-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */ ++ host-wakeup-gpios = <&r_pio 0 5 GPIO_ACTIVE_HIGH>; /* PL5 */ ++ shutdown-gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */ ++ }; + }; + + &usb_otg { +@@ -375,4 +398,4 @@ + usb0_id_det-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */ + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +-}; +\ No newline at end of file ++};