Merge tag 'soc-fixes-5.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 4 Jul 2022 17:41:59 +0000 (10:41 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 4 Jul 2022 17:41:59 +0000 (10:41 -0700)
Pull ARM SoC fixes from Arnd Bergmann:
 "Another set of minor patches for Arm DTS files and soc specific
  drivers:

   - More reference counting bug fixes for DT nodes, and other trivial
     code fixes

   - Multiple code fixes for the Arm SCMI firmware driver to improve
     compatibility with firmware implementations.

   - A patch series for at91 to address power management issues from
     using the wrong DT compatible properties.

   - A series of patches to fix pad settings for NXP imx8mp to leave the
     configuration untouched from the boot loader

   - Additional DT fixes for qualcomm and NXP platforms

   - A boot time fix for stm32mp15 DT

   - Konrad Dybcio becomes an additional reviewer for the Qualcomm
     platforms"

* tag 'soc-fixes-5.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (42 commits)
  soc: qcom: smem: use correct format characters
  ARM: dts: stm32: add missing usbh clock and fix clk order on stm32mp15
  ARM: dts: stm32: delete fixed clock node on STM32MP15-SCMI
  ARM: dts: stm32: DSI should use LSE SCMI clock on DK1/ED1 STM32 board
  ARM: dts: stm32: use the correct clock source for CEC on stm32mp151
  ARM: dts: stm32: fix pwr regulators references to use scmi
  soc: ixp4xx/npe: Fix unused match warning
  ARM: at91: pm: Mark at91_pm_secure_init as __init
  ARM: at91: fix soc detection for SAM9X60 SiPs
  ARM: dts: at91: sama5d2_icp: fix eeprom compatibles
  ARM: dts: at91: sam9x60ek: fix eeprom compatible and size
  ARM: at91: pm: use proper compatibles for sama7g5's rtc and rtt
  ARM: at91: pm: use proper compatibles for sam9x60's rtc and rtt
  ARM: at91: pm: use proper compatible for sama5d2's rtc
  arm64: dts: qcom: msm8992-*: Fix vdd_lvs1_2-supply typo
  firmware: arm_scmi: Remove usage of the deprecated ida_simple_xxx API
  firmware: arm_scmi: Fix response size warning for OPTEE transport
  arm64: dts: imx8mp-icore-mx8mp-edim2.2: correct pad settings
  arm64: dts: imx8mp-phyboard-pollux-rdk: correct i2c2 & mmc settings
  arm64: dts: imx8mp-phyboard-pollux-rdk: correct eqos pad settings
  ...

194 files changed:
Documentation/driver-api/firmware/other_interfaces.rst
MAINTAINERS
Makefile
arch/arm64/mm/hugetlbpage.c
arch/parisc/kernel/asm-offsets.c
arch/parisc/kernel/unaligned.c
arch/powerpc/Kconfig
arch/powerpc/include/asm/bpf_perf_event.h [new file with mode: 0644]
arch/powerpc/include/uapi/asm/bpf_perf_event.h [deleted file]
arch/powerpc/kernel/prom_init_check.sh
arch/powerpc/mm/mem.c
arch/powerpc/mm/nohash/book3e_pgtable.c
arch/powerpc/sysdev/xive/spapr.c
arch/s390/Kconfig
arch/s390/crypto/arch_random.c
arch/s390/include/asm/archrandom.h
arch/s390/include/asm/qdio.h
arch/s390/kernel/setup.c
arch/s390/purgatory/Makefile
drivers/acpi/acpi_video.c
drivers/ata/pata_cs5535.c
drivers/clk/stm32/reset-stm32.c
drivers/cpufreq/amd-pstate.c
drivers/cpufreq/cpufreq-dt-platdev.c
drivers/cpufreq/pmac32-cpufreq.c
drivers/cpufreq/qcom-cpufreq-hw.c
drivers/cpufreq/qoriq-cpufreq.c
drivers/crypto/ccp/sp-platform.c
drivers/devfreq/devfreq.c
drivers/devfreq/event/exynos-ppmu.c
drivers/devfreq/governor_passive.c
drivers/firmware/sysfb.c
drivers/firmware/sysfb_simplefb.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/i915/gem/i915_gem_context.c
drivers/gpu/drm/i915/gem/i915_gem_domain.c
drivers/gpu/drm/i915/i915_driver.c
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
drivers/gpu/drm/msm/dp/dp_display.c
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/vc4/vc4_perfmon.c
drivers/hwmon/ibmaem.c
drivers/hwmon/occ/common.c
drivers/hwmon/occ/common.h
drivers/hwmon/occ/p8_i2c.c
drivers/hwmon/occ/p9_sbe.c
drivers/hwmon/pmbus/ucd9200.c
drivers/infiniband/core/cm.c
drivers/infiniband/hw/qedr/qedr.h
drivers/infiniband/hw/qedr/verbs.c
drivers/md/dm-raid.c
drivers/md/raid5.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_alb.c
drivers/net/caif/caif_virtio.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/hirschmann/hellcreek_ptp.c
drivers/net/dsa/ocelot/felix_vsc9959.c
drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c
drivers/net/ethernet/smsc/epic100.c
drivers/net/phy/ax88796b.c
drivers/net/phy/dp83822.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/sfp.c
drivers/net/tun.c
drivers/net/usb/asix.h
drivers/net/usb/asix_common.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/usbnet.c
drivers/net/virtio_net.c
drivers/nfc/nfcmrvl/i2c.c
drivers/nfc/nfcmrvl/spi.c
drivers/nfc/nxp-nci/i2c.c
drivers/nvdimm/bus.c
drivers/nvme/host/core.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/host/tcp.c
drivers/nvme/target/configfs.c
drivers/nvme/target/core.c
drivers/nvme/target/nvmet.h
drivers/nvme/target/passthru.c
drivers/nvme/target/tcp.c
drivers/platform/mellanox/nvsw-sn2201.c
drivers/platform/x86/Kconfig
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel/pmc/core.c
drivers/platform/x86/panasonic-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/s390/char/sclp.c
drivers/s390/virtio/virtio_ccw.c
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
drivers/thermal/intel/intel_tcc_cooling.c
drivers/vdpa/mlx5/net/mlx5_vnet.c
drivers/vdpa/vdpa_user/vduse_dev.c
drivers/vhost/vdpa.c
drivers/video/fbdev/core/fbmem.c
drivers/virtio/Kconfig
drivers/virtio/virtio.c
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci_modern_dev.c
drivers/virtio/virtio_ring.c
fs/ceph/caps.c
fs/io_uring.c
fs/ksmbd/smb2pdu.c
fs/ksmbd/transport_rdma.c
fs/ksmbd/transport_tcp.c
fs/ksmbd/vfs.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfsd/vfs.c
fs/notify/fanotify/fanotify_user.c
fs/read_write.c
fs/xfs/libxfs/xfs_attr.c
fs/xfs/libxfs/xfs_attr.h
fs/xfs/libxfs/xfs_attr_leaf.c
fs/xfs/libxfs/xfs_attr_leaf.h
fs/xfs/xfs_attr_item.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_icache.c
fs/xfs/xfs_icache.h
fs/xfs/xfs_inode.c
fs/xfs/xfs_log.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_qm_syscalls.c
fs/xfs/xfs_super.c
fs/xfs/xfs_trace.h
include/linux/compiler_types.h
include/linux/devfreq.h
include/linux/dim.h
include/linux/fanotify.h
include/linux/lockref.h
include/linux/netdevice.h
include/linux/phy.h
include/linux/refcount.h
include/linux/sysfb.h
include/linux/virtio_config.h
include/net/netfilter/nf_tables.h
include/uapi/drm/drm_fourcc.h
include/uapi/linux/io_uring.h
include/uapi/linux/mptcp.h
kernel/time/tick-sched.c
lib/lockref.c
lib/sbitmap.c
net/bridge/br_netfilter_hooks.c
net/ipv4/ip_tunnel_core.c
net/ipv4/tcp_ipv4.c
net/ipv6/addrconf.c
net/ipv6/route.c
net/ipv6/seg6_hmac.c
net/ipv6/sit.c
net/mptcp/options.c
net/mptcp/pm.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/ncsi/ncsi-manage.c
net/netfilter/nf_tables_core.c
net/netfilter/nf_tables_trace.c
net/netfilter/nft_set_hash.c
net/rose/rose_timer.c
net/sched/act_api.c
net/socket.c
net/sunrpc/xdr.c
net/tipc/node.c
net/tipc/socket.c
tools/arch/arm64/include/uapi/asm/kvm.h
tools/include/uapi/linux/kvm.h
tools/perf/util/bpf-utils.c
tools/perf/util/bpf_off_cpu.c
tools/perf/util/bpf_skel/off_cpu.bpf.c
tools/perf/util/evsel.c
tools/perf/util/off_cpu.h
tools/perf/util/synthetic-events.c
tools/perf/util/unwind-libunwind-local.c
tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c
tools/testing/selftests/net/Makefile
tools/testing/selftests/net/bpf/Makefile
tools/testing/selftests/net/mptcp/diag.sh
tools/testing/selftests/net/mptcp/mptcp_connect.c
tools/testing/selftests/net/mptcp/mptcp_inq.c
tools/testing/selftests/net/mptcp/mptcp_sockopt.c
tools/testing/selftests/net/tun.c [new file with mode: 0644]
tools/testing/selftests/net/udpgso_bench.sh
tools/testing/selftests/tc-testing/tc-tests/actions/gact.json

index b81794e0cfbb937031d948ff4979d7462ab1c9c9..06ac89adaafba2c6c06718cd314c295ad8d61b82 100644 (file)
@@ -13,6 +13,12 @@ EDD Interfaces
 .. kernel-doc:: drivers/firmware/edd.c
    :internal:
 
+Generic System Framebuffers Interface
+-------------------------------------
+
+.. kernel-doc:: drivers/firmware/sysfb.c
+   :export:
+
 Intel Stratix10 SoC Service Layer
 ---------------------------------
 Some features of the Intel Stratix10 SoC require a level of privilege
index 31f607347820e24c58314a88978803efd2400405..f55aea311af50e06dd1bbe7f0ead75985ad1957c 100644 (file)
@@ -4977,6 +4977,7 @@ Q:        http://patchwork.kernel.org/project/linux-clk/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git
 F:     Documentation/devicetree/bindings/clock/
 F:     drivers/clk/
+F:     include/dt-bindings/clock/
 F:     include/linux/clk-pr*
 F:     include/linux/clk/
 F:     include/linux/of_clk.h
@@ -14398,9 +14399,8 @@ F:      Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml
 F:     sound/soc/codecs/tfa989x.c
 
 NXP-NCI NFC DRIVER
-R:     Charles Gorand <charles.gorand@effinnov.com>
 L:     linux-nfc@lists.01.org (subscribers-only)
-S:     Supported
+S:     Orphan
 F:     Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml
 F:     drivers/nfc/nxp-nci
 
index 8973b285ce6c7eb9d0c4ee590585d6d2f82e1a78..990d2ee79186cae8ccb3ff15c93f636ba3c37fdc 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 19
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc5
 NAME = Superb Owl
 
 # *DOCUMENTATION*
index e2a5ec9fdc0db0289c567090acbc11280e758fc1..3618ef3f6d8181efd61a59081e41d886cb4b34e3 100644 (file)
@@ -214,6 +214,19 @@ static pte_t get_clear_contig(struct mm_struct *mm,
        return orig_pte;
 }
 
+static pte_t get_clear_contig_flush(struct mm_struct *mm,
+                                   unsigned long addr,
+                                   pte_t *ptep,
+                                   unsigned long pgsize,
+                                   unsigned long ncontig)
+{
+       pte_t orig_pte = get_clear_contig(mm, addr, ptep, pgsize, ncontig);
+       struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0);
+
+       flush_tlb_range(&vma, addr, addr + (pgsize * ncontig));
+       return orig_pte;
+}
+
 /*
  * Changing some bits of contiguous entries requires us to follow a
  * Break-Before-Make approach, breaking the whole contiguous set
@@ -447,19 +460,20 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
        int ncontig, i;
        size_t pgsize = 0;
        unsigned long pfn = pte_pfn(pte), dpfn;
+       struct mm_struct *mm = vma->vm_mm;
        pgprot_t hugeprot;
        pte_t orig_pte;
 
        if (!pte_cont(pte))
                return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
 
-       ncontig = find_num_contig(vma->vm_mm, addr, ptep, &pgsize);
+       ncontig = find_num_contig(mm, addr, ptep, &pgsize);
        dpfn = pgsize >> PAGE_SHIFT;
 
        if (!__cont_access_flags_changed(ptep, pte, ncontig))
                return 0;
 
-       orig_pte = get_clear_contig(vma->vm_mm, addr, ptep, pgsize, ncontig);
+       orig_pte = get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
 
        /* Make sure we don't lose the dirty or young state */
        if (pte_dirty(orig_pte))
@@ -470,7 +484,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 
        hugeprot = pte_pgprot(pte);
        for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn)
-               set_pte_at(vma->vm_mm, addr, ptep, pfn_pte(pfn, hugeprot));
+               set_pte_at(mm, addr, ptep, pfn_pte(pfn, hugeprot));
 
        return 1;
 }
@@ -492,7 +506,7 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
        ncontig = find_num_contig(mm, addr, ptep, &pgsize);
        dpfn = pgsize >> PAGE_SHIFT;
 
-       pte = get_clear_contig(mm, addr, ptep, pgsize, ncontig);
+       pte = get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
        pte = pte_wrprotect(pte);
 
        hugeprot = pte_pgprot(pte);
@@ -505,17 +519,15 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
                            unsigned long addr, pte_t *ptep)
 {
+       struct mm_struct *mm = vma->vm_mm;
        size_t pgsize;
        int ncontig;
-       pte_t orig_pte;
 
        if (!pte_cont(READ_ONCE(*ptep)))
                return ptep_clear_flush(vma, addr, ptep);
 
-       ncontig = find_num_contig(vma->vm_mm, addr, ptep, &pgsize);
-       orig_pte = get_clear_contig(vma->vm_mm, addr, ptep, pgsize, ncontig);
-       flush_tlb_range(vma, addr, addr + pgsize * ncontig);
-       return orig_pte;
+       ncontig = find_num_contig(mm, addr, ptep, &pgsize);
+       return get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
 }
 
 static int __init hugetlbpage_init(void)
index 2673d57eeb0083e990e21e9ec18f0f1bfe092b2c..94652e13c2603ee42fb6dbc1f451ba9738577b7e 100644 (file)
@@ -224,8 +224,13 @@ int main(void)
        BLANK();
        DEFINE(ASM_SIGFRAME_SIZE, PARISC_RT_SIGFRAME_SIZE);
        DEFINE(SIGFRAME_CONTEXT_REGS, offsetof(struct rt_sigframe, uc.uc_mcontext) - PARISC_RT_SIGFRAME_SIZE);
+#ifdef CONFIG_64BIT
        DEFINE(ASM_SIGFRAME_SIZE32, PARISC_RT_SIGFRAME_SIZE32);
        DEFINE(SIGFRAME_CONTEXT_REGS32, offsetof(struct compat_rt_sigframe, uc.uc_mcontext) - PARISC_RT_SIGFRAME_SIZE32);
+#else
+       DEFINE(ASM_SIGFRAME_SIZE32, PARISC_RT_SIGFRAME_SIZE);
+       DEFINE(SIGFRAME_CONTEXT_REGS32, offsetof(struct rt_sigframe, uc.uc_mcontext) - PARISC_RT_SIGFRAME_SIZE);
+#endif
        BLANK();
        DEFINE(ICACHE_BASE, offsetof(struct pdc_cache_info, ic_base));
        DEFINE(ICACHE_STRIDE, offsetof(struct pdc_cache_info, ic_stride));
index ed1e88a74dc422cf0069820055507c69d23cf88a..bac581b5ecfc5f85e3cb9a3c63efaa020690756b 100644 (file)
@@ -146,7 +146,7 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
 "      depw    %%r0,31,2,%4\n"
 "1:    ldw     0(%%sr1,%4),%0\n"
 "2:    ldw     4(%%sr1,%4),%3\n"
-"      subi    32,%4,%2\n"
+"      subi    32,%2,%2\n"
 "      mtctl   %2,11\n"
 "      vshd    %0,%3,%0\n"
 "3:    \n"
index c2ce2e60c8f0f65f0c3ca1ad80142946b2a9d0ec..7aa12e88c5800df99123852f15c09e3054951e2e 100644 (file)
@@ -358,6 +358,10 @@ config ARCH_SUSPEND_NONZERO_CPU
        def_bool y
        depends on PPC_POWERNV || PPC_PSERIES
 
+config ARCH_HAS_ADD_PAGES
+       def_bool y
+       depends on ARCH_ENABLE_MEMORY_HOTPLUG
+
 config PPC_DCR_NATIVE
        bool
 
diff --git a/arch/powerpc/include/asm/bpf_perf_event.h b/arch/powerpc/include/asm/bpf_perf_event.h
new file mode 100644 (file)
index 0000000..e8a7b4f
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_BPF_PERF_EVENT_H
+#define _ASM_POWERPC_BPF_PERF_EVENT_H
+
+#include <asm/ptrace.h>
+
+typedef struct user_pt_regs bpf_user_pt_regs_t;
+
+#endif /* _ASM_POWERPC_BPF_PERF_EVENT_H */
diff --git a/arch/powerpc/include/uapi/asm/bpf_perf_event.h b/arch/powerpc/include/uapi/asm/bpf_perf_event.h
deleted file mode 100644 (file)
index 5e1e648..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
-#define _UAPI__ASM_BPF_PERF_EVENT_H__
-
-#include <asm/ptrace.h>
-
-typedef struct user_pt_regs bpf_user_pt_regs_t;
-
-#endif /* _UAPI__ASM_BPF_PERF_EVENT_H__ */
index b183ab9c5107c9236930b3d3d9e1f2c7dd27b302..dfa5f729f774d6607f6e417bb5ca379430b96257 100644 (file)
@@ -13,7 +13,7 @@
 # If you really need to reference something from prom_init.o add
 # it to the list below:
 
-grep "^CONFIG_KASAN=y$" .config >/dev/null
+grep "^CONFIG_KASAN=y$" ${KCONFIG_CONFIG} >/dev/null
 if [ $? -eq 0 ]
 then
        MEM_FUNCS="__memcpy __memset"
index 52b77684acda732beeb0452ea7f0cc3b03415f04..a97128a48817758da93ed2e21b2d1c3313287144 100644 (file)
@@ -105,6 +105,37 @@ void __ref arch_remove_linear_mapping(u64 start, u64 size)
        vm_unmap_aliases();
 }
 
+/*
+ * After memory hotplug the variables max_pfn, max_low_pfn and high_memory need
+ * updating.
+ */
+static void update_end_of_memory_vars(u64 start, u64 size)
+{
+       unsigned long end_pfn = PFN_UP(start + size);
+
+       if (end_pfn > max_pfn) {
+               max_pfn = end_pfn;
+               max_low_pfn = end_pfn;
+               high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
+       }
+}
+
+int __ref add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
+                   struct mhp_params *params)
+{
+       int ret;
+
+       ret = __add_pages(nid, start_pfn, nr_pages, params);
+       if (ret)
+               return ret;
+
+       /* update max_pfn, max_low_pfn and high_memory */
+       update_end_of_memory_vars(start_pfn << PAGE_SHIFT,
+                                 nr_pages << PAGE_SHIFT);
+
+       return ret;
+}
+
 int __ref arch_add_memory(int nid, u64 start, u64 size,
                          struct mhp_params *params)
 {
@@ -115,7 +146,7 @@ int __ref arch_add_memory(int nid, u64 start, u64 size,
        rc = arch_create_linear_mapping(nid, start, size, params);
        if (rc)
                return rc;
-       rc = __add_pages(nid, start_pfn, nr_pages, params);
+       rc = add_pages(nid, start_pfn, nr_pages, params);
        if (rc)
                arch_remove_linear_mapping(start, size);
        return rc;
index 7d4368d055a680700442cdc8293d2dc4ff02db5f..b80fc4a91a534129670e7441dd3d45ccfe3c85f7 100644 (file)
@@ -96,8 +96,8 @@ int __ref map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot)
                pgdp = pgd_offset_k(ea);
                p4dp = p4d_offset(pgdp, ea);
                if (p4d_none(*p4dp)) {
-                       pmdp = early_alloc_pgtable(PMD_TABLE_SIZE);
-                       p4d_populate(&init_mm, p4dp, pmdp);
+                       pudp = early_alloc_pgtable(PUD_TABLE_SIZE);
+                       p4d_populate(&init_mm, p4dp, pudp);
                }
                pudp = pud_offset(p4dp, ea);
                if (pud_none(*pudp)) {
@@ -106,7 +106,7 @@ int __ref map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot)
                }
                pmdp = pmd_offset(pudp, ea);
                if (!pmd_present(*pmdp)) {
-                       ptep = early_alloc_pgtable(PAGE_SIZE);
+                       ptep = early_alloc_pgtable(PTE_TABLE_SIZE);
                        pmd_populate_kernel(&init_mm, pmdp, ptep);
                }
                ptep = pte_offset_kernel(pmdp, ea);
index 7d5128676e830082ba1a21436aa8b99dc2dd12b9..d02911e78cfc16862cd16a80583a9f3a29aea50e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of_fdt.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/bitmap.h>
 #include <linux/cpumask.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
@@ -57,7 +58,7 @@ static int __init xive_irq_bitmap_add(int base, int count)
        spin_lock_init(&xibm->lock);
        xibm->base = base;
        xibm->count = count;
-       xibm->bitmap = kzalloc(xibm->count, GFP_KERNEL);
+       xibm->bitmap = bitmap_zalloc(xibm->count, GFP_KERNEL);
        if (!xibm->bitmap) {
                kfree(xibm);
                return -ENOMEM;
@@ -75,7 +76,7 @@ static void xive_irq_bitmap_remove_all(void)
 
        list_for_each_entry_safe(xibm, tmp, &xive_irq_bitmaps, list) {
                list_del(&xibm->list);
-               kfree(xibm->bitmap);
+               bitmap_free(xibm->bitmap);
                kfree(xibm);
        }
 }
index 91c0b80a8bf04a6f3b1e0e3638291ef249a33a5a..8cd9e56c629ba8c374ab9cd0c0117663809cbd27 100644 (file)
@@ -484,7 +484,6 @@ config KEXEC
 config KEXEC_FILE
        bool "kexec file based system call"
        select KEXEC_CORE
-       select BUILD_BIN2C
        depends on CRYPTO
        depends on CRYPTO_SHA256
        depends on CRYPTO_SHA256_S390
index 56007c763902ae05a47a86976c2af00283ec90f8..1f2d40993c4d2defdc1f8ebc813bd11b93dc135d 100644 (file)
  *
  * Copyright IBM Corp. 2017, 2020
  * Author(s): Harald Freudenberger
- *
- * The s390_arch_random_generate() function may be called from random.c
- * in interrupt context. So this implementation does the best to be very
- * fast. There is a buffer of random data which is asynchronously checked
- * and filled by a workqueue thread.
- * If there are enough bytes in the buffer the s390_arch_random_generate()
- * just delivers these bytes. Otherwise false is returned until the
- * worker thread refills the buffer.
- * The worker fills the rng buffer by pulling fresh entropy from the
- * high quality (but slow) true hardware random generator. This entropy
- * is then spread over the buffer with an pseudo random generator PRNG.
- * As the arch_get_random_seed_long() fetches 8 bytes and the calling
- * function add_interrupt_randomness() counts this as 1 bit entropy the
- * distribution needs to make sure there is in fact 1 bit entropy contained
- * in 8 bytes of the buffer. The current values pull 32 byte entropy
- * and scatter this into a 2048 byte buffer. So 8 byte in the buffer
- * will contain 1 bit of entropy.
- * The worker thread is rescheduled based on the charge level of the
- * buffer but at least with 500 ms delay to avoid too much CPU consumption.
- * So the max. amount of rng data delivered via arch_get_random_seed is
- * limited to 4k bytes per second.
  */
 
 #include <linux/kernel.h>
 #include <linux/atomic.h>
 #include <linux/random.h>
-#include <linux/slab.h>
 #include <linux/static_key.h>
-#include <linux/workqueue.h>
-#include <linux/moduleparam.h>
 #include <asm/cpacf.h>
 
 DEFINE_STATIC_KEY_FALSE(s390_arch_random_available);
 
 atomic64_t s390_arch_random_counter = ATOMIC64_INIT(0);
 EXPORT_SYMBOL(s390_arch_random_counter);
-
-#define ARCH_REFILL_TICKS (HZ/2)
-#define ARCH_PRNG_SEED_SIZE 32
-#define ARCH_RNG_BUF_SIZE 2048
-
-static DEFINE_SPINLOCK(arch_rng_lock);
-static u8 *arch_rng_buf;
-static unsigned int arch_rng_buf_idx;
-
-static void arch_rng_refill_buffer(struct work_struct *);
-static DECLARE_DELAYED_WORK(arch_rng_work, arch_rng_refill_buffer);
-
-bool s390_arch_random_generate(u8 *buf, unsigned int nbytes)
-{
-       /* max hunk is ARCH_RNG_BUF_SIZE */
-       if (nbytes > ARCH_RNG_BUF_SIZE)
-               return false;
-
-       /* lock rng buffer */
-       if (!spin_trylock(&arch_rng_lock))
-               return false;
-
-       /* try to resolve the requested amount of bytes from the buffer */
-       arch_rng_buf_idx -= nbytes;
-       if (arch_rng_buf_idx < ARCH_RNG_BUF_SIZE) {
-               memcpy(buf, arch_rng_buf + arch_rng_buf_idx, nbytes);
-               atomic64_add(nbytes, &s390_arch_random_counter);
-               spin_unlock(&arch_rng_lock);
-               return true;
-       }
-
-       /* not enough bytes in rng buffer, refill is done asynchronously */
-       spin_unlock(&arch_rng_lock);
-
-       return false;
-}
-EXPORT_SYMBOL(s390_arch_random_generate);
-
-static void arch_rng_refill_buffer(struct work_struct *unused)
-{
-       unsigned int delay = ARCH_REFILL_TICKS;
-
-       spin_lock(&arch_rng_lock);
-       if (arch_rng_buf_idx > ARCH_RNG_BUF_SIZE) {
-               /* buffer is exhausted and needs refill */
-               u8 seed[ARCH_PRNG_SEED_SIZE];
-               u8 prng_wa[240];
-               /* fetch ARCH_PRNG_SEED_SIZE bytes of entropy */
-               cpacf_trng(NULL, 0, seed, sizeof(seed));
-               /* blow this entropy up to ARCH_RNG_BUF_SIZE with PRNG */
-               memset(prng_wa, 0, sizeof(prng_wa));
-               cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
-                          &prng_wa, NULL, 0, seed, sizeof(seed));
-               cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
-                          &prng_wa, arch_rng_buf, ARCH_RNG_BUF_SIZE, NULL, 0);
-               arch_rng_buf_idx = ARCH_RNG_BUF_SIZE;
-       }
-       delay += (ARCH_REFILL_TICKS * arch_rng_buf_idx) / ARCH_RNG_BUF_SIZE;
-       spin_unlock(&arch_rng_lock);
-
-       /* kick next check */
-       queue_delayed_work(system_long_wq, &arch_rng_work, delay);
-}
-
-/*
- * Here follows the implementation of s390_arch_get_random_long().
- *
- * The random longs to be pulled by arch_get_random_long() are
- * prepared in an 4K buffer which is filled from the NIST 800-90
- * compliant s390 drbg. By default the random long buffer is refilled
- * 256 times before the drbg itself needs a reseed. The reseed of the
- * drbg is done with 32 bytes fetched from the high quality (but slow)
- * trng which is assumed to deliver 100% entropy. So the 32 * 8 = 256
- * bits of entropy are spread over 256 * 4KB = 1MB serving 131072
- * arch_get_random_long() invocations before reseeded.
- *
- * How often the 4K random long buffer is refilled with the drbg
- * before the drbg is reseeded can be adjusted. There is a module
- * parameter 's390_arch_rnd_long_drbg_reseed' accessible via
- *   /sys/module/arch_random/parameters/rndlong_drbg_reseed
- * or as kernel command line parameter
- *   arch_random.rndlong_drbg_reseed=<value>
- * This parameter tells how often the drbg fills the 4K buffer before
- * it is re-seeded by fresh entropy from the trng.
- * A value of 16 results in reseeding the drbg at every 16 * 4 KB = 64
- * KB with 32 bytes of fresh entropy pulled from the trng. So a value
- * of 16 would result in 256 bits entropy per 64 KB.
- * A value of 256 results in 1MB of drbg output before a reseed of the
- * drbg is done. So this would spread the 256 bits of entropy among 1MB.
- * Setting this parameter to 0 forces the reseed to take place every
- * time the 4K buffer is depleted, so the entropy rises to 256 bits
- * entropy per 4K or 0.5 bit entropy per arch_get_random_long().  With
- * setting this parameter to negative values all this effort is
- * disabled, arch_get_random long() returns false and thus indicating
- * that the arch_get_random_long() feature is disabled at all.
- */
-
-static unsigned long rndlong_buf[512];
-static DEFINE_SPINLOCK(rndlong_lock);
-static int rndlong_buf_index;
-
-static int rndlong_drbg_reseed = 256;
-module_param_named(rndlong_drbg_reseed, rndlong_drbg_reseed, int, 0600);
-MODULE_PARM_DESC(rndlong_drbg_reseed, "s390 arch_get_random_long() drbg reseed");
-
-static inline void refill_rndlong_buf(void)
-{
-       static u8 prng_ws[240];
-       static int drbg_counter;
-
-       if (--drbg_counter < 0) {
-               /* need to re-seed the drbg */
-               u8 seed[32];
-
-               /* fetch seed from trng */
-               cpacf_trng(NULL, 0, seed, sizeof(seed));
-               /* seed drbg */
-               memset(prng_ws, 0, sizeof(prng_ws));
-               cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
-                          &prng_ws, NULL, 0, seed, sizeof(seed));
-               /* re-init counter for drbg */
-               drbg_counter = rndlong_drbg_reseed;
-       }
-
-       /* fill the arch_get_random_long buffer from drbg */
-       cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN, &prng_ws,
-                  (u8 *) rndlong_buf, sizeof(rndlong_buf),
-                  NULL, 0);
-}
-
-bool s390_arch_get_random_long(unsigned long *v)
-{
-       bool rc = false;
-       unsigned long flags;
-
-       /* arch_get_random_long() disabled ? */
-       if (rndlong_drbg_reseed < 0)
-               return false;
-
-       /* try to lock the random long lock */
-       if (!spin_trylock_irqsave(&rndlong_lock, flags))
-               return false;
-
-       if (--rndlong_buf_index >= 0) {
-               /* deliver next long value from the buffer */
-               *v = rndlong_buf[rndlong_buf_index];
-               rc = true;
-               goto out;
-       }
-
-       /* buffer is depleted and needs refill */
-       if (in_interrupt()) {
-               /* delay refill in interrupt context to next caller */
-               rndlong_buf_index = 0;
-               goto out;
-       }
-
-       /* refill random long buffer */
-       refill_rndlong_buf();
-       rndlong_buf_index = ARRAY_SIZE(rndlong_buf);
-
-       /* and provide one random long */
-       *v = rndlong_buf[--rndlong_buf_index];
-       rc = true;
-
-out:
-       spin_unlock_irqrestore(&rndlong_lock, flags);
-       return rc;
-}
-EXPORT_SYMBOL(s390_arch_get_random_long);
-
-static int __init s390_arch_random_init(void)
-{
-       /* all the needed PRNO subfunctions available ? */
-       if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG) &&
-           cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN)) {
-
-               /* alloc arch random working buffer */
-               arch_rng_buf = kmalloc(ARCH_RNG_BUF_SIZE, GFP_KERNEL);
-               if (!arch_rng_buf)
-                       return -ENOMEM;
-
-               /* kick worker queue job to fill the random buffer */
-               queue_delayed_work(system_long_wq,
-                                  &arch_rng_work, ARCH_REFILL_TICKS);
-
-               /* enable arch random to the outside world */
-               static_branch_enable(&s390_arch_random_available);
-       }
-
-       return 0;
-}
-arch_initcall(s390_arch_random_init);
index 5dc712fde3c7f078ca4d26910cd9ff3b130964d7..2c6e1c6ecbe780284c2374d7ee0d4394b1a66fda 100644 (file)
 
 #include <linux/static_key.h>
 #include <linux/atomic.h>
+#include <asm/cpacf.h>
 
 DECLARE_STATIC_KEY_FALSE(s390_arch_random_available);
 extern atomic64_t s390_arch_random_counter;
 
-bool s390_arch_get_random_long(unsigned long *v);
-bool s390_arch_random_generate(u8 *buf, unsigned int nbytes);
-
 static inline bool __must_check arch_get_random_long(unsigned long *v)
 {
-       if (static_branch_likely(&s390_arch_random_available))
-               return s390_arch_get_random_long(v);
        return false;
 }
 
@@ -37,7 +33,9 @@ static inline bool __must_check arch_get_random_int(unsigned int *v)
 static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
 {
        if (static_branch_likely(&s390_arch_random_available)) {
-               return s390_arch_random_generate((u8 *)v, sizeof(*v));
+               cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
+               atomic64_add(sizeof(*v), &s390_arch_random_counter);
+               return true;
        }
        return false;
 }
@@ -45,7 +43,9 @@ static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
 static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
 {
        if (static_branch_likely(&s390_arch_random_available)) {
-               return s390_arch_random_generate((u8 *)v, sizeof(*v));
+               cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
+               atomic64_add(sizeof(*v), &s390_arch_random_counter);
+               return true;
        }
        return false;
 }
index 54ae2dc65e3b20905e901f398e8fe0eb3ab6b9a5..2f983e0b95e09d98be327b75dd79e435fab8fff8 100644 (file)
@@ -133,9 +133,9 @@ struct slibe {
  * @sb_count: number of storage blocks
  * @sba: storage block element addresses
  * @dcount: size of storage block elements
- * @user0: user defineable value
- * @res4: reserved paramater
- * @user1: user defineable value
+ * @user0: user definable value
+ * @res4: reserved parameter
+ * @user1: user definable value
  */
 struct qaob {
        u64 res0[6];
index 8d91eccc096325b47cf21f593da2826ccc420863..0a37f5de286316095598b60242318cf184fa3823 100644 (file)
@@ -875,6 +875,11 @@ static void __init setup_randomness(void)
        if (stsi(vmms, 3, 2, 2) == 0 && vmms->count)
                add_device_randomness(&vmms->vm, sizeof(vmms->vm[0]) * vmms->count);
        memblock_free(vmms, PAGE_SIZE);
+
+#ifdef CONFIG_ARCH_RANDOM
+       if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
+               static_branch_enable(&s390_arch_random_available);
+#endif
 }
 
 /*
index 360ada80d20c3b72766f26fa1cbf138138d2dc2f..d237bc6841cb8608c2bb3118d549d8f9bf9c7c5b 100644 (file)
@@ -48,7 +48,6 @@ OBJCOPYFLAGS_purgatory.ro += --remove-section='.note.*'
 $(obj)/purgatory.ro: $(obj)/purgatory $(obj)/purgatory.chk FORCE
                $(call if_changed,objcopy)
 
-$(obj)/kexec-purgatory.o: $(obj)/kexec-purgatory.S $(obj)/purgatory.ro FORCE
-       $(call if_changed_rule,as_o_S)
+$(obj)/kexec-purgatory.o: $(obj)/purgatory.ro
 
-obj-$(CONFIG_ARCH_HAS_KEXEC_PURGATORY) += kexec-purgatory.o
+obj-y += kexec-purgatory.o
index e07782b1fbb68eb6ca3d7a7552387266519f1d83..43177c20ce4f6d1e50b1acf06a934d39dc22e82f 100644 (file)
@@ -73,6 +73,7 @@ module_param(device_id_scheme, bool, 0444);
 static int only_lcd = -1;
 module_param(only_lcd, int, 0444);
 
+static bool has_backlight;
 static int register_count;
 static DEFINE_MUTEX(register_count_mutex);
 static DEFINE_MUTEX(video_list_lock);
@@ -1222,6 +1223,9 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
        acpi_video_device_bind(video, data);
        acpi_video_device_find_cap(data);
 
+       if (data->cap._BCM && data->cap._BCL)
+               has_backlight = true;
+
        mutex_lock(&video->device_list_lock);
        list_add_tail(&data->entry, &video->video_device_list);
        mutex_unlock(&video->device_list_lock);
@@ -2249,6 +2253,7 @@ void acpi_video_unregister(void)
        if (register_count) {
                acpi_bus_unregister_driver(&acpi_video_bus);
                register_count = 0;
+               has_backlight = false;
        }
        mutex_unlock(&register_count_mutex);
 }
@@ -2270,13 +2275,7 @@ void acpi_video_unregister_backlight(void)
 
 bool acpi_video_handles_brightness_key_presses(void)
 {
-       bool have_video_busses;
-
-       mutex_lock(&video_list_lock);
-       have_video_busses = !list_empty(&video_bus_head);
-       mutex_unlock(&video_list_lock);
-
-       return have_video_busses &&
+       return has_backlight &&
               (report_key_events & REPORT_BRIGHTNESS_KEY_EVENTS);
 }
 EXPORT_SYMBOL(acpi_video_handles_brightness_key_presses);
index 6725931f3c35f571c09912f871b0d89b4c13c47b..c2c3238ff84bfae1b82c7ec2732c94a2d66a930a 100644 (file)
@@ -90,7 +90,7 @@ static void cs5535_set_piomode(struct ata_port *ap, struct ata_device *adev)
        static const u16 pio_cmd_timings[5] = {
                0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131
        };
-       u32 reg, dummy;
+       u32 reg, __maybe_unused dummy;
        struct ata_device *pair = ata_dev_pair(adev);
 
        int mode = adev->pio_mode - XFER_PIO_0;
@@ -129,7 +129,7 @@ static void cs5535_set_dmamode(struct ata_port *ap, struct ata_device *adev)
        static const u32 mwdma_timings[3] = {
                0x7F0FFFF3, 0x7F035352, 0x7F024241
        };
-       u32 reg, dummy;
+       u32 reg, __maybe_unused dummy;
        int mode = adev->dma_mode;
 
        rdmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg, dummy);
index 040870130e4b8058086bf011b49aaf5a81f5a320..e89381528af99179887b2e662155697e1c283a66 100644 (file)
@@ -111,6 +111,7 @@ int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match,
        if (!reset_data)
                return -ENOMEM;
 
+       spin_lock_init(&reset_data->lock);
        reset_data->membase = base;
        reset_data->rcdev.owner = THIS_MODULE;
        reset_data->rcdev.ops = &stm32_reset_ops;
index 7be38bc6a673b09c90d578413b38c731a135dc84..9ac75c1cde9c22fc3bcee6885521477ea1352625 100644 (file)
@@ -566,6 +566,28 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
+static int amd_pstate_cpu_resume(struct cpufreq_policy *policy)
+{
+       int ret;
+
+       ret = amd_pstate_enable(true);
+       if (ret)
+               pr_err("failed to enable amd-pstate during resume, return %d\n", ret);
+
+       return ret;
+}
+
+static int amd_pstate_cpu_suspend(struct cpufreq_policy *policy)
+{
+       int ret;
+
+       ret = amd_pstate_enable(false);
+       if (ret)
+               pr_err("failed to disable amd-pstate during suspend, return %d\n", ret);
+
+       return ret;
+}
+
 /* Sysfs attributes */
 
 /*
@@ -636,6 +658,8 @@ static struct cpufreq_driver amd_pstate_driver = {
        .target         = amd_pstate_target,
        .init           = amd_pstate_cpu_init,
        .exit           = amd_pstate_cpu_exit,
+       .suspend        = amd_pstate_cpu_suspend,
+       .resume         = amd_pstate_cpu_resume,
        .set_boost      = amd_pstate_set_boost,
        .name           = "amd-pstate",
        .attr           = amd_pstate_attr,
index 96de1536e1cbf922dd063d87c99cdad4a5da055c..2c96de3f2d83ccd1ccc57839f9c447513ba54da7 100644 (file)
@@ -127,6 +127,7 @@ static const struct of_device_id blocklist[] __initconst = {
        { .compatible = "mediatek,mt8173", },
        { .compatible = "mediatek,mt8176", },
        { .compatible = "mediatek,mt8183", },
+       { .compatible = "mediatek,mt8186", },
        { .compatible = "mediatek,mt8365", },
        { .compatible = "mediatek,mt8516", },
 
index 20f64a8b0a354d8a7aad6caa12aff6969a20ba38..4b8ee2014da6dbb05a15900e629fea8b63c60a93 100644 (file)
@@ -470,6 +470,10 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
        if (slew_done_gpio_np)
                slew_done_gpio = read_gpio(slew_done_gpio_np);
 
+       of_node_put(volt_gpio_np);
+       of_node_put(freq_gpio_np);
+       of_node_put(slew_done_gpio_np);
+
        /* If we use the frequency GPIOs, calculate the min/max speeds based
         * on the bus frequencies
         */
index 0253731d6d25d20ad132eb4756bb634fda561781..36c79580fba25475de26cd8722625fd7c3ad2d69 100644 (file)
@@ -442,6 +442,9 @@ static int qcom_cpufreq_hw_cpu_online(struct cpufreq_policy *policy)
        struct platform_device *pdev = cpufreq_get_driver_data();
        int ret;
 
+       if (data->throttle_irq <= 0)
+               return 0;
+
        ret = irq_set_affinity_hint(data->throttle_irq, policy->cpus);
        if (ret)
                dev_err(&pdev->dev, "Failed to set CPU affinity of %s[%d]\n",
@@ -469,6 +472,9 @@ static int qcom_cpufreq_hw_cpu_offline(struct cpufreq_policy *policy)
 
 static void qcom_cpufreq_hw_lmh_exit(struct qcom_cpufreq_data *data)
 {
+       if (data->throttle_irq <= 0)
+               return;
+
        free_irq(data->throttle_irq, data);
 }
 
index 6b6b20da2bcfc83846d37a3524de5c4d3f7598f2..573b417e1483307ee23599f08fb4bf17a12c070f 100644 (file)
@@ -275,6 +275,7 @@ static int qoriq_cpufreq_probe(struct platform_device *pdev)
 
        np = of_find_matching_node(NULL, qoriq_cpufreq_blacklist);
        if (np) {
+               of_node_put(np);
                dev_info(&pdev->dev, "Disabling due to erratum A-008083");
                return -ENODEV;
        }
index 9dba52fbee99770af545be7cd187a3f718bb7c84..7d79a8744f9a6a279307b41ab692b2982f28144d 100644 (file)
@@ -85,17 +85,9 @@ static int sp_get_irqs(struct sp_device *sp)
        struct sp_platform *sp_platform = sp->dev_specific;
        struct device *dev = sp->dev;
        struct platform_device *pdev = to_platform_device(dev);
-       unsigned int i, count;
        int ret;
 
-       for (i = 0, count = 0; i < pdev->num_resources; i++) {
-               struct resource *res = &pdev->resource[i];
-
-               if (resource_type(res) == IORESOURCE_IRQ)
-                       count++;
-       }
-
-       sp_platform->irq_count = count;
+       sp_platform->irq_count = platform_irq_count(pdev);
 
        ret = platform_get_irq(pdev, 0);
        if (ret < 0) {
@@ -104,7 +96,7 @@ static int sp_get_irqs(struct sp_device *sp)
        }
 
        sp->psp_irq = ret;
-       if (count == 1) {
+       if (sp_platform->irq_count == 1) {
                sp->ccp_irq = ret;
        } else {
                ret = platform_get_irq(pdev, 1);
index 01474daf45483af90a96e353eac87a31bef162f4..9602141bb8ec49d8fbf47a160616c4a107e51720 100644 (file)
@@ -123,7 +123,7 @@ void devfreq_get_freq_range(struct devfreq *devfreq,
                            unsigned long *min_freq,
                            unsigned long *max_freq)
 {
-       unsigned long *freq_table = devfreq->profile->freq_table;
+       unsigned long *freq_table = devfreq->freq_table;
        s32 qos_min_freq, qos_max_freq;
 
        lockdep_assert_held(&devfreq->lock);
@@ -133,11 +133,11 @@ void devfreq_get_freq_range(struct devfreq *devfreq,
         * The devfreq drivers can initialize this in either ascending or
         * descending order and devfreq core supports both.
         */
-       if (freq_table[0] < freq_table[devfreq->profile->max_state - 1]) {
+       if (freq_table[0] < freq_table[devfreq->max_state - 1]) {
                *min_freq = freq_table[0];
-               *max_freq = freq_table[devfreq->profile->max_state - 1];
+               *max_freq = freq_table[devfreq->max_state - 1];
        } else {
-               *min_freq = freq_table[devfreq->profile->max_state - 1];
+               *min_freq = freq_table[devfreq->max_state - 1];
                *max_freq = freq_table[0];
        }
 
@@ -169,8 +169,8 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
 {
        int lev;
 
-       for (lev = 0; lev < devfreq->profile->max_state; lev++)
-               if (freq == devfreq->profile->freq_table[lev])
+       for (lev = 0; lev < devfreq->max_state; lev++)
+               if (freq == devfreq->freq_table[lev])
                        return lev;
 
        return -EINVAL;
@@ -178,7 +178,6 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
 
 static int set_freq_table(struct devfreq *devfreq)
 {
-       struct devfreq_dev_profile *profile = devfreq->profile;
        struct dev_pm_opp *opp;
        unsigned long freq;
        int i, count;
@@ -188,25 +187,22 @@ static int set_freq_table(struct devfreq *devfreq)
        if (count <= 0)
                return -EINVAL;
 
-       profile->max_state = count;
-       profile->freq_table = devm_kcalloc(devfreq->dev.parent,
-                                       profile->max_state,
-                                       sizeof(*profile->freq_table),
-                                       GFP_KERNEL);
-       if (!profile->freq_table) {
-               profile->max_state = 0;
+       devfreq->max_state = count;
+       devfreq->freq_table = devm_kcalloc(devfreq->dev.parent,
+                                          devfreq->max_state,
+                                          sizeof(*devfreq->freq_table),
+                                          GFP_KERNEL);
+       if (!devfreq->freq_table)
                return -ENOMEM;
-       }
 
-       for (i = 0, freq = 0; i < profile->max_state; i++, freq++) {
+       for (i = 0, freq = 0; i < devfreq->max_state; i++, freq++) {
                opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);
                if (IS_ERR(opp)) {
-                       devm_kfree(devfreq->dev.parent, profile->freq_table);
-                       profile->max_state = 0;
+                       devm_kfree(devfreq->dev.parent, devfreq->freq_table);
                        return PTR_ERR(opp);
                }
                dev_pm_opp_put(opp);
-               profile->freq_table[i] = freq;
+               devfreq->freq_table[i] = freq;
        }
 
        return 0;
@@ -246,7 +242,7 @@ int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
 
        if (lev != prev_lev) {
                devfreq->stats.trans_table[
-                       (prev_lev * devfreq->profile->max_state) + lev]++;
+                       (prev_lev * devfreq->max_state) + lev]++;
                devfreq->stats.total_trans++;
        }
 
@@ -835,6 +831,9 @@ struct devfreq *devfreq_add_device(struct device *dev,
                if (err < 0)
                        goto err_dev;
                mutex_lock(&devfreq->lock);
+       } else {
+               devfreq->freq_table = devfreq->profile->freq_table;
+               devfreq->max_state = devfreq->profile->max_state;
        }
 
        devfreq->scaling_min_freq = find_available_min_freq(devfreq);
@@ -870,8 +869,8 @@ struct devfreq *devfreq_add_device(struct device *dev,
 
        devfreq->stats.trans_table = devm_kzalloc(&devfreq->dev,
                        array3_size(sizeof(unsigned int),
-                                   devfreq->profile->max_state,
-                                   devfreq->profile->max_state),
+                                   devfreq->max_state,
+                                   devfreq->max_state),
                        GFP_KERNEL);
        if (!devfreq->stats.trans_table) {
                mutex_unlock(&devfreq->lock);
@@ -880,7 +879,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
        }
 
        devfreq->stats.time_in_state = devm_kcalloc(&devfreq->dev,
-                       devfreq->profile->max_state,
+                       devfreq->max_state,
                        sizeof(*devfreq->stats.time_in_state),
                        GFP_KERNEL);
        if (!devfreq->stats.time_in_state) {
@@ -932,8 +931,9 @@ struct devfreq *devfreq_add_device(struct device *dev,
        err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,
                                                NULL);
        if (err) {
-               dev_err(dev, "%s: Unable to start governor for the device\n",
-                       __func__);
+               dev_err_probe(dev, err,
+                       "%s: Unable to start governor for the device\n",
+                        __func__);
                goto err_init;
        }
        create_sysfs_files(devfreq, devfreq->governor);
@@ -1665,9 +1665,9 @@ static ssize_t available_frequencies_show(struct device *d,
 
        mutex_lock(&df->lock);
 
-       for (i = 0; i < df->profile->max_state; i++)
+       for (i = 0; i < df->max_state; i++)
                count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
-                               "%lu ", df->profile->freq_table[i]);
+                               "%lu ", df->freq_table[i]);
 
        mutex_unlock(&df->lock);
        /* Truncate the trailing space */
@@ -1690,7 +1690,7 @@ static ssize_t trans_stat_show(struct device *dev,
 
        if (!df->profile)
                return -EINVAL;
-       max_state = df->profile->max_state;
+       max_state = df->max_state;
 
        if (max_state == 0)
                return sprintf(buf, "Not Supported.\n");
@@ -1707,19 +1707,17 @@ static ssize_t trans_stat_show(struct device *dev,
        len += sprintf(buf + len, "           :");
        for (i = 0; i < max_state; i++)
                len += sprintf(buf + len, "%10lu",
-                               df->profile->freq_table[i]);
+                               df->freq_table[i]);
 
        len += sprintf(buf + len, "   time(ms)\n");
 
        for (i = 0; i < max_state; i++) {
-               if (df->profile->freq_table[i]
-                                       == df->previous_freq) {
+               if (df->freq_table[i] == df->previous_freq)
                        len += sprintf(buf + len, "*");
-               } else {
+               else
                        len += sprintf(buf + len, " ");
-               }
-               len += sprintf(buf + len, "%10lu:",
-                               df->profile->freq_table[i]);
+
+               len += sprintf(buf + len, "%10lu:", df->freq_table[i]);
                for (j = 0; j < max_state; j++)
                        len += sprintf(buf + len, "%10u",
                                df->stats.trans_table[(i * max_state) + j]);
@@ -1743,7 +1741,7 @@ static ssize_t trans_stat_store(struct device *dev,
        if (!df->profile)
                return -EINVAL;
 
-       if (df->profile->max_state == 0)
+       if (df->max_state == 0)
                return count;
 
        err = kstrtoint(buf, 10, &value);
@@ -1751,11 +1749,11 @@ static ssize_t trans_stat_store(struct device *dev,
                return -EINVAL;
 
        mutex_lock(&df->lock);
-       memset(df->stats.time_in_state, 0, (df->profile->max_state *
+       memset(df->stats.time_in_state, 0, (df->max_state *
                                        sizeof(*df->stats.time_in_state)));
        memset(df->stats.trans_table, 0, array3_size(sizeof(unsigned int),
-                                       df->profile->max_state,
-                                       df->profile->max_state));
+                                       df->max_state,
+                                       df->max_state));
        df->stats.total_trans = 0;
        df->stats.last_update = get_jiffies_64();
        mutex_unlock(&df->lock);
index 9b849d7811167dfa3675b7f1e86fc89bb8157b5b..a443e7c42dafa050d097dc68446125f43a47ddd7 100644 (file)
@@ -519,15 +519,19 @@ static int of_get_devfreq_events(struct device_node *np,
 
        count = of_get_child_count(events_np);
        desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL);
-       if (!desc)
+       if (!desc) {
+               of_node_put(events_np);
                return -ENOMEM;
+       }
        info->num_events = count;
 
        of_id = of_match_device(exynos_ppmu_id_match, dev);
        if (of_id)
                info->ppmu_type = (enum exynos_ppmu_type)of_id->data;
-       else
+       else {
+               of_node_put(events_np);
                return -EINVAL;
+       }
 
        j = 0;
        for_each_child_of_node(events_np, node) {
index 72c67979ebe11217b9abd66c39222d5c37eab9ef..953cf9a1e9f7f93804cc889db38883bf97ae005d 100644 (file)
@@ -1,4 +1,4 @@
-       // SPDX-License-Identifier: GPL-2.0-only
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * linux/drivers/devfreq/governor_passive.c
  *
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/devfreq.h>
+#include <linux/units.h>
 #include "governor.h"
 
-#define HZ_PER_KHZ     1000
-
 static struct devfreq_cpu_data *
 get_parent_cpu_data(struct devfreq_passive_data *p_data,
                    struct cpufreq_policy *policy)
@@ -34,6 +33,20 @@ get_parent_cpu_data(struct devfreq_passive_data *p_data,
        return NULL;
 }
 
+static void delete_parent_cpu_data(struct devfreq_passive_data *p_data)
+{
+       struct devfreq_cpu_data *parent_cpu_data, *tmp;
+
+       list_for_each_entry_safe(parent_cpu_data, tmp, &p_data->cpu_data_list, node) {
+               list_del(&parent_cpu_data->node);
+
+               if (parent_cpu_data->opp_table)
+                       dev_pm_opp_put_opp_table(parent_cpu_data->opp_table);
+
+               kfree(parent_cpu_data);
+       }
+}
+
 static unsigned long get_target_freq_by_required_opp(struct device *p_dev,
                                                struct opp_table *p_opp_table,
                                                struct opp_table *opp_table,
@@ -131,18 +144,18 @@ static int get_target_freq_with_devfreq(struct devfreq *devfreq,
                goto out;
 
        /* Use interpolation if required opps is not available */
-       for (i = 0; i < parent_devfreq->profile->max_state; i++)
-               if (parent_devfreq->profile->freq_table[i] == *freq)
+       for (i = 0; i < parent_devfreq->max_state; i++)
+               if (parent_devfreq->freq_table[i] == *freq)
                        break;
 
-       if (i == parent_devfreq->profile->max_state)
+       if (i == parent_devfreq->max_state)
                return -EINVAL;
 
-       if (i < devfreq->profile->max_state) {
-               child_freq = devfreq->profile->freq_table[i];
+       if (i < devfreq->max_state) {
+               child_freq = devfreq->freq_table[i];
        } else {
-               count = devfreq->profile->max_state;
-               child_freq = devfreq->profile->freq_table[count - 1];
+               count = devfreq->max_state;
+               child_freq = devfreq->freq_table[count - 1];
        }
 
 out:
@@ -222,8 +235,7 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq)
 {
        struct devfreq_passive_data *p_data
                        = (struct devfreq_passive_data *)devfreq->data;
-       struct devfreq_cpu_data *parent_cpu_data;
-       int cpu, ret = 0;
+       int ret;
 
        if (p_data->nb.notifier_call) {
                ret = cpufreq_unregister_notifier(&p_data->nb,
@@ -232,27 +244,9 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq)
                        return ret;
        }
 
-       for_each_possible_cpu(cpu) {
-               struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-               if (!policy) {
-                       ret = -EINVAL;
-                       continue;
-               }
-
-               parent_cpu_data = get_parent_cpu_data(p_data, policy);
-               if (!parent_cpu_data) {
-                       cpufreq_cpu_put(policy);
-                       continue;
-               }
+       delete_parent_cpu_data(p_data);
 
-               list_del(&parent_cpu_data->node);
-               if (parent_cpu_data->opp_table)
-                       dev_pm_opp_put_opp_table(parent_cpu_data->opp_table);
-               kfree(parent_cpu_data);
-               cpufreq_cpu_put(policy);
-       }
-
-       return ret;
+       return 0;
 }
 
 static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
@@ -336,7 +330,6 @@ err_free_cpu_data:
 err_put_policy:
        cpufreq_cpu_put(policy);
 err:
-       WARN_ON(cpufreq_passive_unregister_notifier(devfreq));
 
        return ret;
 }
@@ -407,8 +400,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq,
        if (!p_data)
                return -EINVAL;
 
-       if (!p_data->this)
-               p_data->this = devfreq;
+       p_data->this = devfreq;
 
        switch (event) {
        case DEVFREQ_GOV_START:
index 2bfbb05f7d896912712679b9999060a2b04e4685..1f276f108cc9364ae949ec32e31321af2f6c4385 100644 (file)
 #include <linux/screen_info.h>
 #include <linux/sysfb.h>
 
+static struct platform_device *pd;
+static DEFINE_MUTEX(disable_lock);
+static bool disabled;
+
+static bool sysfb_unregister(void)
+{
+       if (IS_ERR_OR_NULL(pd))
+               return false;
+
+       platform_device_unregister(pd);
+       pd = NULL;
+
+       return true;
+}
+
+/**
+ * sysfb_disable() - disable the Generic System Framebuffers support
+ *
+ * This disables the registration of system framebuffer devices that match the
+ * generic drivers that make use of the system framebuffer set up by firmware.
+ *
+ * It also unregisters a device if this was already registered by sysfb_init().
+ *
+ * Context: The function can sleep. A @disable_lock mutex is acquired to serialize
+ *          against sysfb_init(), that registers a system framebuffer device.
+ */
+void sysfb_disable(void)
+{
+       mutex_lock(&disable_lock);
+       sysfb_unregister();
+       disabled = true;
+       mutex_unlock(&disable_lock);
+}
+EXPORT_SYMBOL_GPL(sysfb_disable);
+
 static __init int sysfb_init(void)
 {
        struct screen_info *si = &screen_info;
        struct simplefb_platform_data mode;
-       struct platform_device *pd;
        const char *name;
        bool compatible;
-       int ret;
+       int ret = 0;
+
+       mutex_lock(&disable_lock);
+       if (disabled)
+               goto unlock_mutex;
 
        /* try to create a simple-framebuffer device */
        compatible = sysfb_parse_mode(si, &mode);
        if (compatible) {
-               ret = sysfb_create_simplefb(si, &mode);
-               if (!ret)
-                       return 0;
+               pd = sysfb_create_simplefb(si, &mode);
+               if (!IS_ERR(pd))
+                       goto unlock_mutex;
        }
 
        /* if the FB is incompatible, create a legacy framebuffer device */
@@ -60,8 +98,10 @@ static __init int sysfb_init(void)
                name = "platform-framebuffer";
 
        pd = platform_device_alloc(name, 0);
-       if (!pd)
-               return -ENOMEM;
+       if (!pd) {
+               ret = -ENOMEM;
+               goto unlock_mutex;
+       }
 
        sysfb_apply_efi_quirks(pd);
 
@@ -73,9 +113,11 @@ static __init int sysfb_init(void)
        if (ret)
                goto err;
 
-       return 0;
+       goto unlock_mutex;
 err:
        platform_device_put(pd);
+unlock_mutex:
+       mutex_unlock(&disable_lock);
        return ret;
 }
 
index bda8712bfd8c5c40846a036f8d92605f0f995a09..a353e27f83f540b2ad18d11990c3f20de6f76d6e 100644 (file)
@@ -57,8 +57,8 @@ __init bool sysfb_parse_mode(const struct screen_info *si,
        return false;
 }
 
-__init int sysfb_create_simplefb(const struct screen_info *si,
-                                const struct simplefb_platform_data *mode)
+__init struct platform_device *sysfb_create_simplefb(const struct screen_info *si,
+                                                    const struct simplefb_platform_data *mode)
 {
        struct platform_device *pd;
        struct resource res;
@@ -76,7 +76,7 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
                base |= (u64)si->ext_lfb_base << 32;
        if (!base || (u64)(resource_size_t)base != base) {
                printk(KERN_DEBUG "sysfb: inaccessible VRAM base\n");
-               return -EINVAL;
+               return ERR_PTR(-EINVAL);
        }
 
        /*
@@ -93,7 +93,7 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
        length = mode->height * mode->stride;
        if (length > size) {
                printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n");
-               return -EINVAL;
+               return ERR_PTR(-EINVAL);
        }
        length = PAGE_ALIGN(length);
 
@@ -104,11 +104,11 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
        res.start = base;
        res.end = res.start + length - 1;
        if (res.end <= res.start)
-               return -EINVAL;
+               return ERR_PTR(-EINVAL);
 
        pd = platform_device_alloc("simple-framebuffer", 0);
        if (!pd)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        sysfb_apply_efi_quirks(pd);
 
@@ -124,10 +124,10 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
        if (ret)
                goto err_put_device;
 
-       return 0;
+       return pd;
 
 err_put_device:
        platform_device_put(pd);
 
-       return ret;
+       return ERR_PTR(ret);
 }
index 1f8161cd507f007eb2da2d2cea5a10044aa53db3..3b1c675aba3462aa8ab14329a12a95f676f48341 100644 (file)
@@ -714,7 +714,8 @@ int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
 {
        bool all_hub = false;
 
-       if (adev->family == AMDGPU_FAMILY_AI)
+       if (adev->family == AMDGPU_FAMILY_AI ||
+           adev->family == AMDGPU_FAMILY_RV)
                all_hub = true;
 
        return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub);
index 625424f3082b6b8b8d75d54e25ebea86c180e1a9..58df107e3bebacde6e71fc838ac567ac9605318b 100644 (file)
@@ -5164,7 +5164,7 @@ int amdgpu_device_gpu_recover_imp(struct amdgpu_device *adev,
                 */
                amdgpu_unregister_gpu_instance(tmp_adev);
 
-               drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true);
+               drm_fb_helper_set_suspend_unlocked(adev_to_drm(tmp_adev)->fb_helper, true);
 
                /* disable ras on ALL IPs */
                if (!need_emergency_restart &&
index b4cf8717f554eaa4163b73bd87dac91026d93e81..89011bae7588e80e0646c9d63aad590209801a4d 100644 (file)
@@ -320,6 +320,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
        if (!amdgpu_device_has_dc_support(adev)) {
                if (!adev->enable_virtual_display)
                        /* Disable vblank IRQs aggressively for power-saving */
+                       /* XXX: can this be enabled for DC? */
                        adev_to_drm(adev)->vblank_disable_immediate = true;
 
                r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
index 39b425d83bb1a5f52030d14f6bc134ef376bcf0c..9dd2e0601ea8ce0d050d6bf87fa7131c5e9aa20c 100644 (file)
@@ -4259,9 +4259,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
                }
        }
 
-       /* Disable vblank IRQs aggressively for power-saving. */
-       adev_to_drm(adev)->vblank_disable_immediate = true;
-
        /* loops over all connectors on the board */
        for (i = 0; i < link_cnt; i++) {
                struct dc_link *link = NULL;
index ab4c5ab28e4d9fbcd666d341a0d6934c3d2f96dd..321af109d484ff1fcba5026ac00b3adb800b9236 100644 (file)
@@ -933,8 +933,9 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv,
        case I915_CONTEXT_PARAM_PERSISTENCE:
                if (args->size)
                        ret = -EINVAL;
-               ret = proto_context_set_persistence(fpriv->dev_priv, pc,
-                                                   args->value);
+               else
+                       ret = proto_context_set_persistence(fpriv->dev_priv, pc,
+                                                           args->value);
                break;
 
        case I915_CONTEXT_PARAM_PROTECTED_CONTENT:
index 3e5d6057b3ef91cf4a4a8d77cf13f06f1cf60361..1674b0c5802bf0500c6cce1e010f6fb59c8318fe 100644 (file)
@@ -35,12 +35,12 @@ bool i915_gem_cpu_write_needs_clflush(struct drm_i915_gem_object *obj)
        if (obj->cache_dirty)
                return false;
 
-       if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE))
-               return true;
-
        if (IS_DGFX(i915))
                return false;
 
+       if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE))
+               return true;
+
        /* Currently in use by HW (display engine)? Keep flushed. */
        return i915_gem_object_is_framebuffer(obj);
 }
index 90b0ce5051aff6ff4544213ab68e59fc24c3da14..1041b5340465f59b200c4c4a2c1cc172b9d17ff3 100644 (file)
@@ -530,6 +530,7 @@ mask_err:
 static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
 {
        struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
+       struct pci_dev *root_pdev;
        int ret;
 
        if (i915_inject_probe_failure(dev_priv))
@@ -641,6 +642,15 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
 
        intel_bw_init_hw(dev_priv);
 
+       /*
+        * FIXME: Temporary hammer to avoid freezing the machine on our DGFX
+        * This should be totally removed when we handle the pci states properly
+        * on runtime PM and on s2idle cases.
+        */
+       root_pdev = pcie_find_root_port(pdev);
+       if (root_pdev)
+               pci_d3cold_disable(root_pdev);
+
        return 0;
 
 err_msi:
@@ -664,11 +674,16 @@ err_perf:
 static void i915_driver_hw_remove(struct drm_i915_private *dev_priv)
 {
        struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
+       struct pci_dev *root_pdev;
 
        i915_perf_fini(dev_priv);
 
        if (pdev->msi_enabled)
                pci_disable_msi(pdev);
+
+       root_pdev = pcie_find_root_port(pdev);
+       if (root_pdev)
+               pci_d3cold_enable(root_pdev);
 }
 
 /**
@@ -1193,14 +1208,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
                goto out;
        }
 
-       /*
-        * FIXME: Temporary hammer to avoid freezing the machine on our DGFX
-        * This should be totally removed when we handle the pci states properly
-        * on runtime PM and on s2idle cases.
-        */
-       if (suspend_to_idle(dev_priv))
-               pci_d3cold_disable(pdev);
-
        pci_disable_device(pdev);
        /*
         * During hibernation on some platforms the BIOS may try to access
@@ -1365,8 +1372,6 @@ static int i915_drm_resume_early(struct drm_device *dev)
 
        pci_set_master(pdev);
 
-       pci_d3cold_enable(pdev);
-
        disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
 
        ret = vlv_resume_prepare(dev_priv, false);
@@ -1543,7 +1548,6 @@ static int intel_runtime_suspend(struct device *kdev)
 {
        struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
        struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
-       struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
        int ret;
 
        if (drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_RUNTIME_PM(dev_priv)))
@@ -1589,12 +1593,6 @@ static int intel_runtime_suspend(struct device *kdev)
                drm_err(&dev_priv->drm,
                        "Unclaimed access detected prior to suspending\n");
 
-       /*
-        * FIXME: Temporary hammer to avoid freezing the machine on our DGFX
-        * This should be totally removed when we handle the pci states properly
-        * on runtime PM and on s2idle cases.
-        */
-       pci_d3cold_disable(pdev);
        rpm->suspended = true;
 
        /*
@@ -1633,7 +1631,6 @@ static int intel_runtime_resume(struct device *kdev)
 {
        struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
        struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
-       struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
        int ret;
 
        if (drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_RUNTIME_PM(dev_priv)))
@@ -1646,7 +1643,6 @@ static int intel_runtime_resume(struct device *kdev)
 
        intel_opregion_notify_adapter(dev_priv, PCI_D0);
        rpm->suspended = false;
-       pci_d3cold_enable(pdev);
        if (intel_uncore_unclaimed_mmio(&dev_priv->uncore))
                drm_dbg(&dev_priv->drm,
                        "Unclaimed access during suspend, bios?\n");
index 3a462e327e0ed4fb3cccd738341492a8b2b3aee4..a1b8c4592943722d2686c3152a0bc3f8ee962aed 100644 (file)
@@ -1251,12 +1251,13 @@ static void dpu_encoder_vblank_callback(struct drm_encoder *drm_enc,
        DPU_ATRACE_BEGIN("encoder_vblank_callback");
        dpu_enc = to_dpu_encoder_virt(drm_enc);
 
+       atomic_inc(&phy_enc->vsync_cnt);
+
        spin_lock_irqsave(&dpu_enc->enc_spinlock, lock_flags);
        if (dpu_enc->crtc)
                dpu_crtc_vblank_callback(dpu_enc->crtc);
        spin_unlock_irqrestore(&dpu_enc->enc_spinlock, lock_flags);
 
-       atomic_inc(&phy_enc->vsync_cnt);
        DPU_ATRACE_END("encoder_vblank_callback");
 }
 
index 59da348ff33965c59703423f6a030f5331012385..0ec809ab06e72a2bbf291ade1195179bf782d8e1 100644 (file)
@@ -252,11 +252,6 @@ static int dpu_encoder_phys_wb_atomic_check(
        DPU_DEBUG("[atomic_check:%d, \"%s\",%d,%d]\n",
                        phys_enc->wb_idx, mode->name, mode->hdisplay, mode->vdisplay);
 
-       if (!conn_state->writeback_job || !conn_state->writeback_job->fb)
-               return 0;
-
-       fb = conn_state->writeback_job->fb;
-
        if (!conn_state || !conn_state->connector) {
                DPU_ERROR("invalid connector state\n");
                return -EINVAL;
@@ -267,6 +262,11 @@ static int dpu_encoder_phys_wb_atomic_check(
                return -EINVAL;
        }
 
+       if (!conn_state->writeback_job || !conn_state->writeback_job->fb)
+               return 0;
+
+       fb = conn_state->writeback_job->fb;
+
        DPU_DEBUG("[fb_id:%u][fb:%u,%u]\n", fb->base.id,
                        fb->width, fb->height);
 
index ec26855079c181a76cfb0d405f70d3c5a6ec6575..239c8e3f2fbdc89bcdb92ac16d64e9e980c35931 100644 (file)
@@ -316,6 +316,8 @@ static void dp_display_unbind(struct device *dev, struct device *master,
 
        dp_power_client_deinit(dp->power);
        dp_aux_unregister(dp->aux);
+       dp->drm_dev = NULL;
+       dp->aux->drm_dev = NULL;
        priv->dp[dp->id] = NULL;
 }
 
index 3c3a0cfade369b96e39ce408990079eaa8e0c6cf..c9e4aeb14f4ac0a9ccbcf35e26d833cf0cbdc234 100644 (file)
@@ -928,7 +928,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
                                                    INT_MAX, GFP_KERNEL);
        }
        if (submit->fence_id < 0) {
-               ret = submit->fence_id = 0;
+               ret = submit->fence_id;
                submit->fence_id = 0;
        }
 
index c7f5adb6bcf8b36c993f194e88b99e98eb14fce0..79a74184d732804f7f168c8fd1f44b5003d36376 100644 (file)
 
 void vc4_perfmon_get(struct vc4_perfmon *perfmon)
 {
-       struct vc4_dev *vc4 = perfmon->dev;
+       struct vc4_dev *vc4;
 
+       if (!perfmon)
+               return;
+
+       vc4 = perfmon->dev;
        if (WARN_ON_ONCE(vc4->is_vc5))
                return;
 
-       if (perfmon)
-               refcount_inc(&perfmon->refcnt);
+       refcount_inc(&perfmon->refcnt);
 }
 
 void vc4_perfmon_put(struct vc4_perfmon *perfmon)
index 5c4cf742f5ae7bf6c190b279d31f2001a91cb5d6..157e232aace0c499df6cd878b96c246ed8334c51 100644 (file)
@@ -550,7 +550,7 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
 
        res = platform_device_add(data->pdev);
        if (res)
-               goto ipmi_err;
+               goto dev_add_err;
 
        platform_set_drvdata(data->pdev, data);
 
@@ -598,7 +598,9 @@ hwmon_reg_err:
        ipmi_destroy_user(data->ipmi.user);
 ipmi_err:
        platform_set_drvdata(data->pdev, NULL);
-       platform_device_unregister(data->pdev);
+       platform_device_del(data->pdev);
+dev_add_err:
+       platform_device_put(data->pdev);
 dev_err:
        ida_free(&aem_ida, data->id);
 id_err:
@@ -690,7 +692,7 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
 
        res = platform_device_add(data->pdev);
        if (res)
-               goto ipmi_err;
+               goto dev_add_err;
 
        platform_set_drvdata(data->pdev, data);
 
@@ -738,7 +740,9 @@ hwmon_reg_err:
        ipmi_destroy_user(data->ipmi.user);
 ipmi_err:
        platform_set_drvdata(data->pdev, NULL);
-       platform_device_unregister(data->pdev);
+       platform_device_del(data->pdev);
+dev_add_err:
+       platform_device_put(data->pdev);
 dev_err:
        ida_free(&aem_ida, data->id);
 id_err:
index ea070b91e5b981badd923e235fa7b096354f0c21..157b73a3da29fb51ca571c6329b93179caa6b2df 100644 (file)
@@ -145,7 +145,7 @@ static int occ_poll(struct occ *occ)
        cmd[6] = 0;                     /* checksum lsb */
 
        /* mutex should already be locked if necessary */
-       rc = occ->send_cmd(occ, cmd, sizeof(cmd));
+       rc = occ->send_cmd(occ, cmd, sizeof(cmd), &occ->resp, sizeof(occ->resp));
        if (rc) {
                occ->last_error = rc;
                if (occ->error_count++ > OCC_ERROR_COUNT_THRESHOLD)
@@ -182,6 +182,7 @@ static int occ_set_user_power_cap(struct occ *occ, u16 user_power_cap)
 {
        int rc;
        u8 cmd[8];
+       u8 resp[8];
        __be16 user_power_cap_be = cpu_to_be16(user_power_cap);
 
        cmd[0] = 0;     /* sequence number */
@@ -198,7 +199,7 @@ static int occ_set_user_power_cap(struct occ *occ, u16 user_power_cap)
        if (rc)
                return rc;
 
-       rc = occ->send_cmd(occ, cmd, sizeof(cmd));
+       rc = occ->send_cmd(occ, cmd, sizeof(cmd), resp, sizeof(resp));
 
        mutex_unlock(&occ->lock);
 
index 64d5ec7e169b04982951a66cc0c8710ee836de96..7ac4b2febce65f218b55f89a9c8ef6520eb5cab5 100644 (file)
@@ -96,7 +96,8 @@ struct occ {
 
        int powr_sample_time_us;        /* average power sample time */
        u8 poll_cmd_data;               /* to perform OCC poll command */
-       int (*send_cmd)(struct occ *occ, u8 *cmd, size_t len);
+       int (*send_cmd)(struct occ *occ, u8 *cmd, size_t len, void *resp,
+                       size_t resp_len);
 
        unsigned long next_update;
        struct mutex lock;              /* lock OCC access */
index da39ea28df3122652a744454785c03c5e498e97f..b221be1f35f31e3a57382a34d146cd1fc72c2450 100644 (file)
@@ -111,7 +111,8 @@ static int p8_i2c_occ_putscom_be(struct i2c_client *client, u32 address,
                                      be32_to_cpu(data1));
 }
 
-static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
+static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len,
+                              void *resp, size_t resp_len)
 {
        int i, rc;
        unsigned long start;
@@ -120,7 +121,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
        const long wait_time = msecs_to_jiffies(OCC_CMD_IN_PRG_WAIT_MS);
        struct p8_i2c_occ *ctx = to_p8_i2c_occ(occ);
        struct i2c_client *client = ctx->client;
-       struct occ_response *resp = &occ->resp;
+       struct occ_response *or = (struct occ_response *)resp;
 
        start = jiffies;
 
@@ -151,7 +152,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
                        return rc;
 
                /* wait for OCC */
-               if (resp->return_status == OCC_RESP_CMD_IN_PRG) {
+               if (or->return_status == OCC_RESP_CMD_IN_PRG) {
                        rc = -EALREADY;
 
                        if (time_after(jiffies, start + timeout))
@@ -163,7 +164,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
        } while (rc);
 
        /* check the OCC response */
-       switch (resp->return_status) {
+       switch (or->return_status) {
        case OCC_RESP_CMD_IN_PRG:
                rc = -ETIMEDOUT;
                break;
@@ -192,8 +193,8 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
        if (rc < 0)
                return rc;
 
-       data_length = get_unaligned_be16(&resp->data_length);
-       if (data_length > OCC_RESP_DATA_BYTES)
+       data_length = get_unaligned_be16(&or->data_length);
+       if ((data_length + 7) > resp_len)
                return -EMSGSIZE;
 
        /* fetch the rest of the response data */
index 42fc7b97bb34b55ed5dc4ea73e31ff8b2a7a1af4..a91937e28e12bf634a8466ad9e181e684a747ade 100644 (file)
@@ -78,11 +78,10 @@ done:
        return notify;
 }
 
-static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
+static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len,
+                              void *resp, size_t resp_len)
 {
-       struct occ_response *resp = &occ->resp;
        struct p9_sbe_occ *ctx = to_p9_sbe_occ(occ);
-       size_t resp_len = sizeof(*resp);
        int rc;
 
        rc = fsi_occ_submit(ctx->sbe, cmd, len, resp, &resp_len);
@@ -96,7 +95,7 @@ static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
                return rc;
        }
 
-       switch (resp->return_status) {
+       switch (((struct occ_response *)resp)->return_status) {
        case OCC_RESP_CMD_IN_PRG:
                rc = -ETIMEDOUT;
                break;
index 6bc3273e31e72a88b63a1bd4715075e422830575..3ad375a76f3ecb20699a68776bf127744c37e0c1 100644 (file)
@@ -148,7 +148,7 @@ static int ucd9200_probe(struct i2c_client *client)
         * This only affects the READ_IOUT and READ_TEMPERATURE2 registers.
         * READ_IOUT will return the sum of currents of all phases of a rail,
         * and READ_TEMPERATURE2 will return the maximum temperature detected
-        * for the the phases of the rail.
+        * for the phases of the rail.
         */
        for (i = 0; i < info->pages; i++) {
                /*
index 1c107d6d03b990d9ea0a33dc4bb1e634b073ed87..b985e0d9bc05e91b10685f670c766aaee45673d0 100644 (file)
@@ -1252,8 +1252,10 @@ struct ib_cm_id *ib_cm_insert_listen(struct ib_device *device,
                return ERR_CAST(cm_id_priv);
 
        err = cm_init_listen(cm_id_priv, service_id, 0);
-       if (err)
+       if (err) {
+               ib_destroy_cm_id(&cm_id_priv->id);
                return ERR_PTR(err);
+       }
 
        spin_lock_irq(&cm_id_priv->lock);
        listen_id_priv = cm_insert_listen(cm_id_priv, cm_handler);
index 8def88cfa30091eac2f8f609459d57dcc0f224a2..db9ef3e1eb97c638132b69cf3a770e094ab7f85b 100644 (file)
@@ -418,6 +418,7 @@ struct qedr_qp {
        u32 sq_psn;
        u32 qkey;
        u32 dest_qp_num;
+       u8 timeout;
 
        /* Relevant to qps created from kernel space only (ULPs) */
        u8 prev_wqe_size;
index f0f43b6db89ee9669d96a99e3010ad192df92b06..03ed7c0fae505eb3d7c7f62eda3fe51feea60cbf 100644 (file)
@@ -2613,6 +2613,8 @@ int qedr_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                        1 << max_t(int, attr->timeout - 8, 0);
                else
                        qp_params.ack_timeout = 0;
+
+               qp->timeout = attr->timeout;
        }
 
        if (attr_mask & IB_QP_RETRY_CNT) {
@@ -2772,7 +2774,7 @@ int qedr_query_qp(struct ib_qp *ibqp,
        rdma_ah_set_dgid_raw(&qp_attr->ah_attr, &params.dgid.bytes[0]);
        rdma_ah_set_port_num(&qp_attr->ah_attr, 1);
        rdma_ah_set_sl(&qp_attr->ah_attr, 0);
-       qp_attr->timeout = params.timeout;
+       qp_attr->timeout = qp->timeout;
        qp_attr->rnr_retry = params.rnr_retry;
        qp_attr->retry_cnt = params.retry_cnt;
        qp_attr->min_rnr_timer = params.min_rnr_nak_timer;
index 9526ccbedafbac9ad74c413b2968a3bdc5da776d..80c9f7134e9b951906e2758075d2fcd203e1ff2e 100644 (file)
@@ -1001,12 +1001,13 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size)
 static int validate_raid_redundancy(struct raid_set *rs)
 {
        unsigned int i, rebuild_cnt = 0;
-       unsigned int rebuilds_per_group = 0, copies;
+       unsigned int rebuilds_per_group = 0, copies, raid_disks;
        unsigned int group_size, last_group_start;
 
-       for (i = 0; i < rs->md.raid_disks; i++)
-               if (!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
-                   !rs->dev[i].rdev.sb_page)
+       for (i = 0; i < rs->raid_disks; i++)
+               if (!test_bit(FirstUse, &rs->dev[i].rdev.flags) &&
+                   ((!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
+                     !rs->dev[i].rdev.sb_page)))
                        rebuild_cnt++;
 
        switch (rs->md.level) {
@@ -1046,8 +1047,9 @@ static int validate_raid_redundancy(struct raid_set *rs)
                 *          A    A    B    B    C
                 *          C    D    D    E    E
                 */
+               raid_disks = min(rs->raid_disks, rs->md.raid_disks);
                if (__is_raid10_near(rs->md.new_layout)) {
-                       for (i = 0; i < rs->md.raid_disks; i++) {
+                       for (i = 0; i < raid_disks; i++) {
                                if (!(i % copies))
                                        rebuilds_per_group = 0;
                                if ((!rs->dev[i].rdev.sb_page ||
@@ -1070,10 +1072,10 @@ static int validate_raid_redundancy(struct raid_set *rs)
                 * results in the need to treat the last (potentially larger)
                 * set differently.
                 */
-               group_size = (rs->md.raid_disks / copies);
-               last_group_start = (rs->md.raid_disks / group_size) - 1;
+               group_size = (raid_disks / copies);
+               last_group_start = (raid_disks / group_size) - 1;
                last_group_start *= group_size;
-               for (i = 0; i < rs->md.raid_disks; i++) {
+               for (i = 0; i < raid_disks; i++) {
                        if (!(i % copies) && !(i > last_group_start))
                                rebuilds_per_group = 0;
                        if ((!rs->dev[i].rdev.sb_page ||
@@ -1588,7 +1590,7 @@ static sector_t __rdev_sectors(struct raid_set *rs)
 {
        int i;
 
-       for (i = 0; i < rs->md.raid_disks; i++) {
+       for (i = 0; i < rs->raid_disks; i++) {
                struct md_rdev *rdev = &rs->dev[i].rdev;
 
                if (!test_bit(Journal, &rdev->flags) &&
@@ -3766,13 +3768,13 @@ static int raid_iterate_devices(struct dm_target *ti,
        unsigned int i;
        int r = 0;
 
-       for (i = 0; !r && i < rs->md.raid_disks; i++)
-               if (rs->dev[i].data_dev)
-                       r = fn(ti,
-                                rs->dev[i].data_dev,
-                                0, /* No offset on data devs */
-                                rs->md.dev_sectors,
-                                data);
+       for (i = 0; !r && i < rs->raid_disks; i++) {
+               if (rs->dev[i].data_dev) {
+                       r = fn(ti, rs->dev[i].data_dev,
+                              0, /* No offset on data devs */
+                              rs->md.dev_sectors, data);
+               }
+       }
 
        return r;
 }
index 5d09256d7f81857d4a6861ef192a6f0d385118a8..20e53b167f81f5d4dd03507edb9eb93bf3ed7411 100644 (file)
@@ -7933,7 +7933,7 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
        int err = 0;
        int number = rdev->raid_disk;
        struct md_rdev __rcu **rdevp;
-       struct disk_info *p = conf->disks + number;
+       struct disk_info *p;
        struct md_rdev *tmp;
 
        print_raid5_conf(conf);
@@ -7952,6 +7952,9 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
                log_exit(conf);
                return 0;
        }
+       if (unlikely(number >= conf->pool_size))
+               return 0;
+       p = conf->disks + number;
        if (rdev == rcu_access_pointer(p->rdev))
                rdevp = &p->rdev;
        else if (rdev == rcu_access_pointer(p->replacement))
@@ -8062,6 +8065,7 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev)
         */
        if (rdev->saved_raid_disk >= 0 &&
            rdev->saved_raid_disk >= first &&
+           rdev->saved_raid_disk <= last &&
            conf->disks[rdev->saved_raid_disk].rdev == NULL)
                first = rdev->saved_raid_disk;
 
index a86b1f71762ea455dddd8a879f7770aca32e67ad..d7fb33c078e81a1c8242d5af793b328a19b79bd2 100644 (file)
@@ -2228,7 +2228,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
                                temp_aggregator->num_of_ports--;
                                if (__agg_active_ports(temp_aggregator) == 0) {
                                        select_new_active_agg = temp_aggregator->is_active;
-                                       ad_clear_agg(temp_aggregator);
+                                       if (temp_aggregator->num_of_ports == 0)
+                                               ad_clear_agg(temp_aggregator);
                                        if (select_new_active_agg) {
                                                slave_info(bond->dev, slave->dev, "Removing an active aggregator\n");
                                                /* select new active aggregator */
index 303c8d32d451e24345222ec105a1986d53a94eb4..007d43e46dcb0cb1cee1f23623bd161a6c32a45c 100644 (file)
@@ -1302,12 +1302,12 @@ int bond_alb_initialize(struct bonding *bond, int rlb_enabled)
                return res;
 
        if (rlb_enabled) {
-               bond->alb_info.rlb_enabled = 1;
                res = rlb_initialize(bond);
                if (res) {
                        tlb_deinitialize(bond);
                        return res;
                }
+               bond->alb_info.rlb_enabled = 1;
        } else {
                bond->alb_info.rlb_enabled = 0;
        }
index 5458f57177a0aa6bf980da662fd8f9f0257bbb3b..0b0f234b0b508020aacb1b1ac40a747e86788a11 100644 (file)
@@ -722,13 +722,21 @@ static int cfv_probe(struct virtio_device *vdev)
        /* Carrier is off until netdevice is opened */
        netif_carrier_off(netdev);
 
+       /* serialize netdev register + virtio_device_ready() with ndo_open() */
+       rtnl_lock();
+
        /* register Netdev */
-       err = register_netdev(netdev);
+       err = register_netdevice(netdev);
        if (err) {
+               rtnl_unlock();
                dev_err(&vdev->dev, "Unable to register netdev (%d)\n", err);
                goto err;
        }
 
+       virtio_device_ready(vdev);
+
+       rtnl_unlock();
+
        debugfs_init(cfv);
 
        return 0;
index 87e81c636339f9720260807521f917ff57f74fb9..be0edfa093d047fb6f0a4b7b3caeef2ae75b42f4 100644 (file)
@@ -878,6 +878,11 @@ static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port,
                if (duplex == DUPLEX_FULL)
                        reg |= DUPLX_MODE;
 
+               if (tx_pause)
+                       reg |= TXFLOW_CNTL;
+               if (rx_pause)
+                       reg |= RXFLOW_CNTL;
+
                core_writel(priv, reg, offset);
        }
 
index 2572c6087bb5a192756248410a380ffd8a391388..b28baab6d56a17bcc1bb44846aefcbcdff4a08d4 100644 (file)
@@ -300,6 +300,7 @@ static int hellcreek_led_setup(struct hellcreek *hellcreek)
        const char *label, *state;
        int ret = -EINVAL;
 
+       of_node_get(hellcreek->dev->of_node);
        leds = of_find_node_by_name(hellcreek->dev->of_node, "leds");
        if (!leds) {
                dev_err(hellcreek->dev, "No LEDs specified in device tree!\n");
index 570d0204b7bef6b54a24b1193e86cc0f4a2f113d..9c27b9b0128db89c6c023dd35e616734fe31e236 100644 (file)
@@ -1886,6 +1886,8 @@ static void vsc9959_psfp_sgi_table_del(struct ocelot *ocelot,
 static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index,
                                      struct felix_stream_filter_counters *counters)
 {
+       mutex_lock(&ocelot->stats_lock);
+
        ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(index),
                   SYS_STAT_CFG_STAT_VIEW_M,
                   SYS_STAT_CFG);
@@ -1900,6 +1902,8 @@ static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index,
                     SYS_STAT_CFG_STAT_VIEW(index) |
                     SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10),
                     SYS_STAT_CFG);
+
+       mutex_unlock(&ocelot->stats_lock);
 }
 
 static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port,
index cc51149790ff686b02d85e490c879bf58e3241b7..3d5d39a52fe645b286aa8cc5a54937daf5a8b281 100644 (file)
@@ -52,7 +52,7 @@
 
 #define    CN93_SDP_EPF_RINFO_SRN(val)           ((val) & 0xFF)
 #define    CN93_SDP_EPF_RINFO_RPVF(val)          (((val) >> 32) & 0xF)
-#define    CN93_SDP_EPF_RINFO_NVFS(val)          (((val) >> 48) && 0xFF)
+#define    CN93_SDP_EPF_RINFO_NVFS(val)          (((val) >> 48) & 0xFF)
 
 /* SDP Function select */
 #define    CN93_SDP_FUNC_SEL_EPF_BIT_POS         8
index 9dbb573d53eaf6f5913f4c6bfe96440929d17fcd..0d8a0068e4ca1c1b004ac752a9905554317cacb9 100644 (file)
@@ -4415,6 +4415,8 @@ static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
        return 0;
 
 err_nexthop_neigh_init:
+       list_del(&nh->router_list_node);
+       mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
        mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
        return err;
 }
@@ -6740,6 +6742,7 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
                                  const struct fib6_info *rt)
 {
        struct net_device *dev = rt->fib6_nh->fib_nh_dev;
+       int err;
 
        nh->nhgi = nh_grp->nhgi;
        nh->nh_weight = rt->fib6_nh->fib_nh_weight;
@@ -6755,7 +6758,16 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
                return 0;
        nh->ifindex = dev->ifindex;
 
-       return mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
+       err = mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
+       if (err)
+               goto err_nexthop_type_init;
+
+       return 0;
+
+err_nexthop_type_init:
+       list_del(&nh->router_list_node);
+       mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
+       return err;
 }
 
 static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
index 3429660cd2e5d4b778b1f18beaaeec6ddeb4cc5a..5edc8b7176c822eabbf319c9d1afd3e9f984fe81 100644 (file)
@@ -396,6 +396,9 @@ static int sparx5_handle_port_mdb_add(struct net_device *dev,
        u32 mact_entry;
        int res, err;
 
+       if (!sparx5_netdevice_check(dev))
+               return -EOPNOTSUPP;
+
        if (netif_is_bridge_master(v->obj.orig_dev)) {
                sparx5_mact_learn(spx5, PGID_CPU, v->addr, v->vid);
                return 0;
@@ -466,6 +469,9 @@ static int sparx5_handle_port_mdb_del(struct net_device *dev,
        u32 mact_entry, res, pgid_entry[3];
        int err;
 
+       if (!sparx5_netdevice_check(dev))
+               return -EOPNOTSUPP;
+
        if (netif_is_bridge_master(v->obj.orig_dev)) {
                sparx5_mact_forget(spx5, v->addr, v->vid);
                return 0;
index a0654e88444cff62651e91d252f23008c6a1bab5..0329caf63279c54b6d6614336aec107edd6b972c 100644 (file)
@@ -1515,14 +1515,14 @@ static void epic_remove_one(struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct epic_private *ep = netdev_priv(dev);
 
+       unregister_netdev(dev);
        dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, ep->tx_ring,
                          ep->tx_ring_dma);
        dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE, ep->rx_ring,
                          ep->rx_ring_dma);
-       unregister_netdev(dev);
        pci_iounmap(pdev, ep->ioaddr);
-       pci_release_regions(pdev);
        free_netdev(dev);
+       pci_release_regions(pdev);
        pci_disable_device(pdev);
        /* pci_power_off(pdev, -1); */
 }
index 4578963375055391b503011787672bbff41e11c8..0f1e617a26c9154b2fda61956fe4689ad3ede911 100644 (file)
@@ -88,8 +88,10 @@ static void asix_ax88772a_link_change_notify(struct phy_device *phydev)
        /* Reset PHY, otherwise MII_LPA will provide outdated information.
         * This issue is reproducible only with some link partner PHYs
         */
-       if (phydev->state == PHY_NOLINK && phydev->drv->soft_reset)
-               phydev->drv->soft_reset(phydev);
+       if (phydev->state == PHY_NOLINK) {
+               phy_init_hw(phydev);
+               phy_start_aneg(phydev);
+       }
 }
 
 static struct phy_driver asix_driver[] = {
index e6ad3a494d32cce28139f54c2e64f52a440ee66b..8549e0e356c9b42226003c0f02a734192b9d5e18 100644 (file)
@@ -229,9 +229,7 @@ static int dp83822_config_intr(struct phy_device *phydev)
                if (misr_status < 0)
                        return misr_status;
 
-               misr_status |= (DP83822_RX_ERR_HF_INT_EN |
-                               DP83822_FALSE_CARRIER_HF_INT_EN |
-                               DP83822_LINK_STAT_INT_EN |
+               misr_status |= (DP83822_LINK_STAT_INT_EN |
                                DP83822_ENERGY_DET_INT_EN |
                                DP83822_LINK_QUAL_INT_EN);
 
index ef62f357b76d949a57b461c530c5d9c5efb786c7..8d3ee3a6495b45754095c8c8a0c842ced8a26434 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <linux/atomic.h>
+#include <linux/suspend.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
 #include <net/sock.h>
@@ -976,6 +977,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
        struct phy_driver *drv = phydev->drv;
        irqreturn_t ret;
 
+       /* Wakeup interrupts may occur during a system sleep transition.
+        * Postpone handling until the PHY has resumed.
+        */
+       if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+               struct net_device *netdev = phydev->attached_dev;
+
+               if (netdev) {
+                       struct device *parent = netdev->dev.parent;
+
+                       if (netdev->wol_enabled)
+                               pm_system_wakeup();
+                       else if (device_may_wakeup(&netdev->dev))
+                               pm_wakeup_dev_event(&netdev->dev, 0, true);
+                       else if (parent && device_may_wakeup(parent))
+                               pm_wakeup_dev_event(parent, 0, true);
+               }
+
+               phydev->irq_rerun = 1;
+               disable_irq_nosync(irq);
+               return IRQ_HANDLED;
+       }
+
        mutex_lock(&phydev->lock);
        ret = drv->handle_interrupt(phydev);
        mutex_unlock(&phydev->lock);
index 431a8719c6359b24029c8964405ab165b21edde6..46acddd865a782f550bf11536a67010b4485d5dc 100644 (file)
@@ -278,6 +278,15 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
        if (phydev->mac_managed_pm)
                return 0;
 
+       /* Wakeup interrupts may occur during the system sleep transition when
+        * the PHY is inaccessible. Set flag to postpone handling until the PHY
+        * has resumed. Wait for concurrent interrupt handler to complete.
+        */
+       if (phy_interrupt_is_valid(phydev)) {
+               phydev->irq_suspended = 1;
+               synchronize_irq(phydev->irq);
+       }
+
        /* We must stop the state machine manually, otherwise it stops out of
         * control, possibly with the phydev->lock held. Upon resume, netdev
         * may call phy routines that try to grab the same lock, and that may
@@ -315,6 +324,20 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
        if (ret < 0)
                return ret;
 no_resume:
+       if (phy_interrupt_is_valid(phydev)) {
+               phydev->irq_suspended = 0;
+               synchronize_irq(phydev->irq);
+
+               /* Rerun interrupts which were postponed by phy_interrupt()
+                * because they occurred during the system sleep transition.
+                */
+               if (phydev->irq_rerun) {
+                       phydev->irq_rerun = 0;
+                       enable_irq(phydev->irq);
+                       irq_wake_thread(phydev->irq, phydev);
+               }
+       }
+
        if (phydev->attached_dev && phydev->adjust_link)
                phy_start_machine(phydev);
 
index 9a5d5a10560fb135d5b7a547795dfcdce6e94377..e7b0e12cc75bf3825ebf8d2044f6d6f92d95bf13 100644 (file)
@@ -2516,7 +2516,7 @@ static int sfp_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, sfp);
 
-       err = devm_add_action(sfp->dev, sfp_cleanup, sfp);
+       err = devm_add_action_or_reset(sfp->dev, sfp_cleanup, sfp);
        if (err < 0)
                return err;
 
index 87a635aac0084a1008276a0bab2f5f794fc04c52..259b2b84b2b39453cb3de27c632cf9bc0f9ce2b7 100644 (file)
@@ -273,6 +273,12 @@ static void tun_napi_init(struct tun_struct *tun, struct tun_file *tfile,
        }
 }
 
+static void tun_napi_enable(struct tun_file *tfile)
+{
+       if (tfile->napi_enabled)
+               napi_enable(&tfile->napi);
+}
+
 static void tun_napi_disable(struct tun_file *tfile)
 {
        if (tfile->napi_enabled)
@@ -634,7 +640,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
        tun = rtnl_dereference(tfile->tun);
 
        if (tun && clean) {
-               tun_napi_disable(tfile);
+               if (!tfile->detached)
+                       tun_napi_disable(tfile);
                tun_napi_del(tfile);
        }
 
@@ -653,8 +660,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
                if (clean) {
                        RCU_INIT_POINTER(tfile->tun, NULL);
                        sock_put(&tfile->sk);
-               } else
+               } else {
                        tun_disable_queue(tun, tfile);
+                       tun_napi_disable(tfile);
+               }
 
                synchronize_net();
                tun_flow_delete_by_queue(tun, tun->numqueues + 1);
@@ -727,6 +736,7 @@ static void tun_detach_all(struct net_device *dev)
                sock_put(&tfile->sk);
        }
        list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) {
+               tun_napi_del(tfile);
                tun_enable_queue(tfile);
                tun_queue_purge(tfile);
                xdp_rxq_info_unreg(&tfile->xdp_rxq);
@@ -807,6 +817,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
 
        if (tfile->detached) {
                tun_enable_queue(tfile);
+               tun_napi_enable(tfile);
        } else {
                sock_hold(&tfile->sk);
                tun_napi_init(tun, tfile, napi, napi_frags);
index 2c81236c6c7c6f9c8e6c4032fc58f6099acf0b55..45d3cc5cc355e1eced9b406d3a39807db72e444f 100644 (file)
         AX_MEDIUM_RE)
 
 #define AX88772_MEDIUM_DEFAULT \
-       (AX_MEDIUM_FD | AX_MEDIUM_RFC | \
-        AX_MEDIUM_TFC | AX_MEDIUM_PS | \
+       (AX_MEDIUM_FD | AX_MEDIUM_PS | \
         AX_MEDIUM_AC | AX_MEDIUM_RE)
 
 /* AX88772 & AX88178 RX_CTL values */
index 632fa6c1d5e307e69abc0d0ec439ba7e6bc9fbdd..b4a1b7abcfc97911dcd3d7bcbd1a93bb5d60745f 100644 (file)
@@ -431,6 +431,7 @@ void asix_adjust_link(struct net_device *netdev)
 
        asix_write_medium_mode(dev, mode, 0);
        phy_print_status(phydev);
+       usbnet_link_change(dev, phydev->link, 0);
 }
 
 int asix_write_gpio(struct usbnet *dev, u16 value, int sleep, int in_pm)
index 4704ed6f00efe98307c9f51f064cb024c42795ca..ac2d400d1d6cdfa74d462ea07d0367a12629bb0a 100644 (file)
@@ -1472,6 +1472,42 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
         * are bundled into this buffer and where we can find an array of
         * per-packet metadata (which contains elements encoded into u16).
         */
+
+       /* SKB contents for current firmware:
+        *   <packet 1> <padding>
+        *   ...
+        *   <packet N> <padding>
+        *   <per-packet metadata entry 1> <dummy header>
+        *   ...
+        *   <per-packet metadata entry N> <dummy header>
+        *   <padding2> <rx_hdr>
+        *
+        * where:
+        *   <packet N> contains pkt_len bytes:
+        *              2 bytes of IP alignment pseudo header
+        *              packet received
+        *   <per-packet metadata entry N> contains 4 bytes:
+        *              pkt_len and fields AX_RXHDR_*
+        *   <padding>  0-7 bytes to terminate at
+        *              8 bytes boundary (64-bit).
+        *   <padding2> 4 bytes to make rx_hdr terminate at
+        *              8 bytes boundary (64-bit)
+        *   <dummy-header> contains 4 bytes:
+        *              pkt_len=0 and AX_RXHDR_DROP_ERR
+        *   <rx-hdr>   contains 4 bytes:
+        *              pkt_cnt and hdr_off (offset of
+        *                <per-packet metadata entry 1>)
+        *
+        * pkt_cnt is number of entrys in the per-packet metadata.
+        * In current firmware there is 2 entrys per packet.
+        * The first points to the packet and the
+        *  second is a dummy header.
+        * This was done probably to align fields in 64-bit and
+        *  maintain compatibility with old firmware.
+        * This code assumes that <dummy header> and <padding2> are
+        *  optional.
+        */
+
        if (skb->len < 4)
                return 0;
        skb_trim(skb, skb->len - 4);
@@ -1485,51 +1521,66 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        /* Make sure that the bounds of the metadata array are inside the SKB
         * (and in front of the counter at the end).
         */
-       if (pkt_cnt * 2 + hdr_off > skb->len)
+       if (pkt_cnt * 4 + hdr_off > skb->len)
                return 0;
        pkt_hdr = (u32 *)(skb->data + hdr_off);
 
        /* Packets must not overlap the metadata array */
        skb_trim(skb, hdr_off);
 
-       for (; ; pkt_cnt--, pkt_hdr++) {
+       for (; pkt_cnt > 0; pkt_cnt--, pkt_hdr++) {
+               u16 pkt_len_plus_padd;
                u16 pkt_len;
 
                le32_to_cpus(pkt_hdr);
                pkt_len = (*pkt_hdr >> 16) & 0x1fff;
+               pkt_len_plus_padd = (pkt_len + 7) & 0xfff8;
 
-               if (pkt_len > skb->len)
+               /* Skip dummy header used for alignment
+                */
+               if (pkt_len == 0)
+                       continue;
+
+               if (pkt_len_plus_padd > skb->len)
                        return 0;
 
                /* Check CRC or runt packet */
-               if (((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) == 0) &&
-                   pkt_len >= 2 + ETH_HLEN) {
-                       bool last = (pkt_cnt == 0);
-
-                       if (last) {
-                               ax_skb = skb;
-                       } else {
-                               ax_skb = skb_clone(skb, GFP_ATOMIC);
-                               if (!ax_skb)
-                                       return 0;
-                       }
-                       ax_skb->len = pkt_len;
-                       /* Skip IP alignment pseudo header */
-                       skb_pull(ax_skb, 2);
-                       skb_set_tail_pointer(ax_skb, ax_skb->len);
-                       ax_skb->truesize = pkt_len + sizeof(struct sk_buff);
-                       ax88179_rx_checksum(ax_skb, pkt_hdr);
+               if ((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) ||
+                   pkt_len < 2 + ETH_HLEN) {
+                       dev->net->stats.rx_errors++;
+                       skb_pull(skb, pkt_len_plus_padd);
+                       continue;
+               }
 
-                       if (last)
-                               return 1;
+               /* last packet */
+               if (pkt_len_plus_padd == skb->len) {
+                       skb_trim(skb, pkt_len);
 
-                       usbnet_skb_return(dev, ax_skb);
+                       /* Skip IP alignment pseudo header */
+                       skb_pull(skb, 2);
+
+                       skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd);
+                       ax88179_rx_checksum(skb, pkt_hdr);
+                       return 1;
                }
 
-               /* Trim this packet away from the SKB */
-               if (!skb_pull(skb, (pkt_len + 7) & 0xFFF8))
+               ax_skb = skb_clone(skb, GFP_ATOMIC);
+               if (!ax_skb)
                        return 0;
+               skb_trim(ax_skb, pkt_len);
+
+               /* Skip IP alignment pseudo header */
+               skb_pull(ax_skb, 2);
+
+               skb->truesize = pkt_len_plus_padd +
+                               SKB_DATA_ALIGN(sizeof(struct sk_buff));
+               ax88179_rx_checksum(ax_skb, pkt_hdr);
+               usbnet_skb_return(dev, ax_skb);
+
+               skb_pull(skb, pkt_len_plus_padd);
        }
+
+       return 0;
 }
 
 static struct sk_buff *
index 1cb6dab3e2d042fd3f1f9d91185eea7f6f1531a4..e2135ab87a6ed66be181c77e0cdd363d5347c74e 100644 (file)
@@ -2004,7 +2004,7 @@ static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
                   cmd, reqtype, value, index, size);
 
        if (size) {
-               buf = kmalloc(size, GFP_KERNEL);
+               buf = kmalloc(size, GFP_NOIO);
                if (!buf)
                        goto out;
        }
@@ -2036,7 +2036,7 @@ static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
                   cmd, reqtype, value, index, size);
 
        if (data) {
-               buf = kmemdup(data, size, GFP_KERNEL);
+               buf = kmemdup(data, size, GFP_NOIO);
                if (!buf)
                        goto out;
        } else {
index 969a67970e71c7f2318a3df77cd5fd120cd424db..356cf8dd4164b94f3183aeab1f19b0a2335dbd74 100644 (file)
@@ -3642,14 +3642,20 @@ static int virtnet_probe(struct virtio_device *vdev)
        if (vi->has_rss || vi->has_rss_hash_report)
                virtnet_init_default_rss(vi);
 
-       err = register_netdev(dev);
+       /* serialize netdev register + virtio_device_ready() with ndo_open() */
+       rtnl_lock();
+
+       err = register_netdevice(dev);
        if (err) {
                pr_debug("virtio_net: registering device failed\n");
+               rtnl_unlock();
                goto free_failover;
        }
 
        virtio_device_ready(vdev);
 
+       rtnl_unlock();
+
        err = virtnet_cpu_notif_add(vi);
        if (err) {
                pr_debug("virtio_net: registering cpu notifier failed\n");
index ceef81d93ac997b0caba42a5d5122dbd29afa82c..01329b91d59d547577680a058bced7d001c6c364 100644 (file)
@@ -167,9 +167,9 @@ static int nfcmrvl_i2c_parse_dt(struct device_node *node,
                pdata->irq_polarity = IRQF_TRIGGER_RISING;
 
        ret = irq_of_parse_and_map(node, 0);
-       if (ret < 0) {
-               pr_err("Unable to get irq, error: %d\n", ret);
-               return ret;
+       if (!ret) {
+               pr_err("Unable to get irq\n");
+               return -EINVAL;
        }
        pdata->irq = ret;
 
index a38e2fcdfd39fc7270310636e4495462e1ba998d..ad3359a4942c7ce24d91d366463c42fff639935b 100644 (file)
@@ -115,9 +115,9 @@ static int nfcmrvl_spi_parse_dt(struct device_node *node,
        }
 
        ret = irq_of_parse_and_map(node, 0);
-       if (ret < 0) {
-               pr_err("Unable to get irq, error: %d\n", ret);
-               return ret;
+       if (!ret) {
+               pr_err("Unable to get irq\n");
+               return -EINVAL;
        }
        pdata->irq = ret;
 
index 7e451c10985df35f31d7ffb34c7e9ebc1edee954..ae2ba08d8ac3f3b7b4fa9db0b8ec8093d2258723 100644 (file)
@@ -122,7 +122,9 @@ static int nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy *phy,
        skb_put_data(*skb, &header, NXP_NCI_FW_HDR_LEN);
 
        r = i2c_master_recv(client, skb_put(*skb, frame_len), frame_len);
-       if (r != frame_len) {
+       if (r < 0) {
+               goto fw_read_exit_free_skb;
+       } else if (r != frame_len) {
                nfc_err(&client->dev,
                        "Invalid frame length: %u (expected %zu)\n",
                        r, frame_len);
@@ -162,8 +164,13 @@ static int nxp_nci_i2c_nci_read(struct nxp_nci_i2c_phy *phy,
 
        skb_put_data(*skb, (void *)&header, NCI_CTRL_HDR_SIZE);
 
+       if (!header.plen)
+               return 0;
+
        r = i2c_master_recv(client, skb_put(*skb, header.plen), header.plen);
-       if (r != header.plen) {
+       if (r < 0) {
+               goto nci_read_exit_free_skb;
+       } else if (r != header.plen) {
                nfc_err(&client->dev,
                        "Invalid frame payload length: %u (expected %u)\n",
                        r, header.plen);
index a4fc17db707c9b99afcbad8342f093a55516d6ea..b38d0355b0ac3b4e7b6c836d71f635e491e937ea 100644 (file)
@@ -176,8 +176,8 @@ static int nvdimm_clear_badblocks_region(struct device *dev, void *data)
        ndr_end = nd_region->ndr_start + nd_region->ndr_size - 1;
 
        /* make sure we are in the region */
-       if (ctx->phys < nd_region->ndr_start
-                       || (ctx->phys + ctx->cleared) > ndr_end)
+       if (ctx->phys < nd_region->ndr_start ||
+           (ctx->phys + ctx->cleared - 1) > ndr_end)
                return 0;
 
        sector = (ctx->phys - nd_region->ndr_start) / 512;
index b3d9c29aba1e6af1a9c9682e279cdabe4a8c5031..ec6ac298d8de2b707ec6e079b46c9df48d15f9c4 100644 (file)
@@ -4595,6 +4595,8 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl)
        nvme_stop_failfast_work(ctrl);
        flush_work(&ctrl->async_event_work);
        cancel_work_sync(&ctrl->fw_act_work);
+       if (ctrl->ops->stop_ctrl)
+               ctrl->ops->stop_ctrl(ctrl);
 }
 EXPORT_SYMBOL_GPL(nvme_stop_ctrl);
 
index 0da94b233feda837070277ee5a46318328cad1df..5558f88121579d9ccd203b10701d81910369e4e4 100644 (file)
@@ -502,6 +502,7 @@ struct nvme_ctrl_ops {
        void (*free_ctrl)(struct nvme_ctrl *ctrl);
        void (*submit_async_event)(struct nvme_ctrl *ctrl);
        void (*delete_ctrl)(struct nvme_ctrl *ctrl);
+       void (*stop_ctrl)(struct nvme_ctrl *ctrl);
        int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size);
        void (*print_device_info)(struct nvme_ctrl *ctrl);
 };
index d7b24ee1728599fed9b2e5a6b1ab6351de8b130a..e7af2234e53b930e377b96e5a5fbffd4229be274 100644 (file)
@@ -3469,8 +3469,11 @@ static const struct pci_device_id nvme_id_table[] = {
        { PCI_DEVICE(0x1b4b, 0x1092),   /* Lexar 256 GB SSD */
                .driver_data = NVME_QUIRK_NO_NS_DESC_LIST |
                                NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+       { PCI_DEVICE(0x1cc1, 0x33f8),   /* ADATA IM2P33F8ABR1 1 TB */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x10ec, 0x5762),   /* ADATA SX6000LNP */
-               .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+               .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN |
+                               NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1cc1, 0x8201),   /* ADATA SX8200PNP 512GB */
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
                                NVME_QUIRK_IGNORE_DEV_SUBNQN, },
index f2a5e1ea508a7af0f5f986b33f33a5668682f378..46c2dcf72f7ea4cc50c43c01ceb136c7d602e9d2 100644 (file)
@@ -1048,6 +1048,14 @@ static void nvme_rdma_teardown_io_queues(struct nvme_rdma_ctrl *ctrl,
        }
 }
 
+static void nvme_rdma_stop_ctrl(struct nvme_ctrl *nctrl)
+{
+       struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(nctrl);
+
+       cancel_work_sync(&ctrl->err_work);
+       cancel_delayed_work_sync(&ctrl->reconnect_work);
+}
+
 static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)
 {
        struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(nctrl);
@@ -2252,9 +2260,6 @@ static const struct blk_mq_ops nvme_rdma_admin_mq_ops = {
 
 static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown)
 {
-       cancel_work_sync(&ctrl->err_work);
-       cancel_delayed_work_sync(&ctrl->reconnect_work);
-
        nvme_rdma_teardown_io_queues(ctrl, shutdown);
        nvme_stop_admin_queue(&ctrl->ctrl);
        if (shutdown)
@@ -2304,6 +2309,7 @@ static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = {
        .submit_async_event     = nvme_rdma_submit_async_event,
        .delete_ctrl            = nvme_rdma_delete_ctrl,
        .get_address            = nvmf_get_address,
+       .stop_ctrl              = nvme_rdma_stop_ctrl,
 };
 
 /*
index bb67538d241b657dec9ee4bac33029920c493d9d..7a9e6ffa23429079269de605dff903e1df95255d 100644 (file)
@@ -1180,8 +1180,7 @@ done:
        } else if (ret < 0) {
                dev_err(queue->ctrl->ctrl.device,
                        "failed to send request %d\n", ret);
-               if (ret != -EPIPE && ret != -ECONNRESET)
-                       nvme_tcp_fail_request(queue->request);
+               nvme_tcp_fail_request(queue->request);
                nvme_tcp_done_send_req(queue);
        }
        return ret;
@@ -2194,9 +2193,6 @@ static void nvme_tcp_error_recovery_work(struct work_struct *work)
 
 static void nvme_tcp_teardown_ctrl(struct nvme_ctrl *ctrl, bool shutdown)
 {
-       cancel_work_sync(&to_tcp_ctrl(ctrl)->err_work);
-       cancel_delayed_work_sync(&to_tcp_ctrl(ctrl)->connect_work);
-
        nvme_tcp_teardown_io_queues(ctrl, shutdown);
        nvme_stop_admin_queue(ctrl);
        if (shutdown)
@@ -2236,6 +2232,12 @@ out_fail:
        nvme_tcp_reconnect_or_remove(ctrl);
 }
 
+static void nvme_tcp_stop_ctrl(struct nvme_ctrl *ctrl)
+{
+       cancel_work_sync(&to_tcp_ctrl(ctrl)->err_work);
+       cancel_delayed_work_sync(&to_tcp_ctrl(ctrl)->connect_work);
+}
+
 static void nvme_tcp_free_ctrl(struct nvme_ctrl *nctrl)
 {
        struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
@@ -2557,6 +2559,7 @@ static const struct nvme_ctrl_ops nvme_tcp_ctrl_ops = {
        .submit_async_event     = nvme_tcp_submit_async_event,
        .delete_ctrl            = nvme_tcp_delete_ctrl,
        .get_address            = nvmf_get_address,
+       .stop_ctrl              = nvme_tcp_stop_ctrl,
 };
 
 static bool
index e44b2988759ec2b1ed343f410de1cce40f2f48b4..ff77c3d2354fa48e351509d36210c3979ef13aaa 100644 (file)
@@ -773,11 +773,31 @@ static ssize_t nvmet_passthru_io_timeout_store(struct config_item *item,
 }
 CONFIGFS_ATTR(nvmet_passthru_, io_timeout);
 
+static ssize_t nvmet_passthru_clear_ids_show(struct config_item *item,
+               char *page)
+{
+       return sprintf(page, "%u\n", to_subsys(item->ci_parent)->clear_ids);
+}
+
+static ssize_t nvmet_passthru_clear_ids_store(struct config_item *item,
+               const char *page, size_t count)
+{
+       struct nvmet_subsys *subsys = to_subsys(item->ci_parent);
+       unsigned int clear_ids;
+
+       if (kstrtouint(page, 0, &clear_ids))
+               return -EINVAL;
+       subsys->clear_ids = clear_ids;
+       return count;
+}
+CONFIGFS_ATTR(nvmet_passthru_, clear_ids);
+
 static struct configfs_attribute *nvmet_passthru_attrs[] = {
        &nvmet_passthru_attr_device_path,
        &nvmet_passthru_attr_enable,
        &nvmet_passthru_attr_admin_timeout,
        &nvmet_passthru_attr_io_timeout,
+       &nvmet_passthru_attr_clear_ids,
        NULL,
 };
 
index 90e75324dae0562146022151335d4810f6911ccc..c27660a660d9aebfa3f01714125810712125f4e8 100644 (file)
@@ -1374,6 +1374,12 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
        ctrl->port = req->port;
        ctrl->ops = req->ops;
 
+#ifdef CONFIG_NVME_TARGET_PASSTHRU
+       /* By default, set loop targets to clear IDS by default */
+       if (ctrl->port->disc_addr.trtype == NVMF_TRTYPE_LOOP)
+               subsys->clear_ids = 1;
+#endif
+
        INIT_WORK(&ctrl->async_event_work, nvmet_async_event_work);
        INIT_LIST_HEAD(&ctrl->async_events);
        INIT_RADIX_TREE(&ctrl->p2p_ns_map, GFP_KERNEL);
index 69818752a33a58d3a6dd7b9c6786b320a187ffd0..2b3e5719f24e4c948cfadc8b9b19c462d79b63b1 100644 (file)
@@ -249,6 +249,7 @@ struct nvmet_subsys {
        struct config_group     passthru_group;
        unsigned int            admin_timeout;
        unsigned int            io_timeout;
+       unsigned int            clear_ids;
 #endif /* CONFIG_NVME_TARGET_PASSTHRU */
 
 #ifdef CONFIG_BLK_DEV_ZONED
index b1f7efab391803a783eedd482e1c2ae3410a1715..6f39a29828b1228463649e0523b129a022c0463f 100644 (file)
@@ -30,6 +30,53 @@ void nvmet_passthrough_override_cap(struct nvmet_ctrl *ctrl)
                ctrl->cap &= ~(1ULL << 43);
 }
 
+static u16 nvmet_passthru_override_id_descs(struct nvmet_req *req)
+{
+       struct nvmet_ctrl *ctrl = req->sq->ctrl;
+       u16 status = NVME_SC_SUCCESS;
+       int pos, len;
+       bool csi_seen = false;
+       void *data;
+       u8 csi;
+
+       if (!ctrl->subsys->clear_ids)
+               return status;
+
+       data = kzalloc(NVME_IDENTIFY_DATA_SIZE, GFP_KERNEL);
+       if (!data)
+               return NVME_SC_INTERNAL;
+
+       status = nvmet_copy_from_sgl(req, 0, data, NVME_IDENTIFY_DATA_SIZE);
+       if (status)
+               goto out_free;
+
+       for (pos = 0; pos < NVME_IDENTIFY_DATA_SIZE; pos += len) {
+               struct nvme_ns_id_desc *cur = data + pos;
+
+               if (cur->nidl == 0)
+                       break;
+               if (cur->nidt == NVME_NIDT_CSI) {
+                       memcpy(&csi, cur + 1, NVME_NIDT_CSI_LEN);
+                       csi_seen = true;
+                       break;
+               }
+               len = sizeof(struct nvme_ns_id_desc) + cur->nidl;
+       }
+
+       memset(data, 0, NVME_IDENTIFY_DATA_SIZE);
+       if (csi_seen) {
+               struct nvme_ns_id_desc *cur = data;
+
+               cur->nidt = NVME_NIDT_CSI;
+               cur->nidl = NVME_NIDT_CSI_LEN;
+               memcpy(cur + 1, &csi, NVME_NIDT_CSI_LEN);
+       }
+       status = nvmet_copy_to_sgl(req, 0, data, NVME_IDENTIFY_DATA_SIZE);
+out_free:
+       kfree(data);
+       return status;
+}
+
 static u16 nvmet_passthru_override_id_ctrl(struct nvmet_req *req)
 {
        struct nvmet_ctrl *ctrl = req->sq->ctrl;
@@ -152,6 +199,11 @@ static u16 nvmet_passthru_override_id_ns(struct nvmet_req *req)
         */
        id->mc = 0;
 
+       if (req->sq->ctrl->subsys->clear_ids) {
+               memset(id->nguid, 0, NVME_NIDT_NGUID_LEN);
+               memset(id->eui64, 0, NVME_NIDT_EUI64_LEN);
+       }
+
        status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id));
 
 out_free:
@@ -176,6 +228,9 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
                case NVME_ID_CNS_NS:
                        nvmet_passthru_override_id_ns(req);
                        break;
+               case NVME_ID_CNS_NS_DESC_LIST:
+                       nvmet_passthru_override_id_descs(req);
+                       break;
                }
        } else if (status < 0)
                status = NVME_SC_INTERNAL;
index 2793554e622ee63fb8eb8e4af6688fa2c1a4dd9e..0a9542599ad1c9d898509140132f634be0587ab6 100644 (file)
@@ -405,7 +405,7 @@ err:
        return NVME_SC_INTERNAL;
 }
 
-static void nvmet_tcp_send_ddgst(struct ahash_request *hash,
+static void nvmet_tcp_calc_ddgst(struct ahash_request *hash,
                struct nvmet_tcp_cmd *cmd)
 {
        ahash_request_set_crypt(hash, cmd->req.sg,
@@ -413,23 +413,6 @@ static void nvmet_tcp_send_ddgst(struct ahash_request *hash,
        crypto_ahash_digest(hash);
 }
 
-static void nvmet_tcp_recv_ddgst(struct ahash_request *hash,
-               struct nvmet_tcp_cmd *cmd)
-{
-       struct scatterlist sg;
-       struct kvec *iov;
-       int i;
-
-       crypto_ahash_init(hash);
-       for (i = 0, iov = cmd->iov; i < cmd->nr_mapped; i++, iov++) {
-               sg_init_one(&sg, iov->iov_base, iov->iov_len);
-               ahash_request_set_crypt(hash, &sg, NULL, iov->iov_len);
-               crypto_ahash_update(hash);
-       }
-       ahash_request_set_crypt(hash, NULL, (void *)&cmd->exp_ddgst, 0);
-       crypto_ahash_final(hash);
-}
-
 static void nvmet_setup_c2h_data_pdu(struct nvmet_tcp_cmd *cmd)
 {
        struct nvme_tcp_data_pdu *pdu = cmd->data_pdu;
@@ -454,7 +437,7 @@ static void nvmet_setup_c2h_data_pdu(struct nvmet_tcp_cmd *cmd)
 
        if (queue->data_digest) {
                pdu->hdr.flags |= NVME_TCP_F_DDGST;
-               nvmet_tcp_send_ddgst(queue->snd_hash, cmd);
+               nvmet_tcp_calc_ddgst(queue->snd_hash, cmd);
        }
 
        if (cmd->queue->hdr_digest) {
@@ -1137,7 +1120,7 @@ static void nvmet_tcp_prep_recv_ddgst(struct nvmet_tcp_cmd *cmd)
 {
        struct nvmet_tcp_queue *queue = cmd->queue;
 
-       nvmet_tcp_recv_ddgst(queue->rcv_hash, cmd);
+       nvmet_tcp_calc_ddgst(queue->rcv_hash, cmd);
        queue->offset = 0;
        queue->left = NVME_TCP_DIGEST_LENGTH;
        queue->rcv_state = NVMET_TCP_RECV_DDGST;
index 2923daf63b75d663ebaad745309c555ad824d8cb..7b9c107c17ce61ab85a4c5411fb6711064f9c879 100644 (file)
@@ -890,6 +890,7 @@ nvsw_sn2201_create_static_devices(struct nvsw_sn2201 *nvsw_sn2201,
                                  int size)
 {
        struct mlxreg_hotplug_device *dev = devs;
+       int ret;
        int i;
 
        /* Create I2C static devices. */
@@ -901,6 +902,7 @@ nvsw_sn2201_create_static_devices(struct nvsw_sn2201 *nvsw_sn2201,
                                dev->nr, dev->brdinfo->addr);
 
                        dev->adapter = NULL;
+                       ret = PTR_ERR(dev->client);
                        goto fail_create_static_devices;
                }
        }
@@ -914,7 +916,7 @@ fail_create_static_devices:
                dev->client = NULL;
                dev->adapter = NULL;
        }
-       return IS_ERR(dev->client);
+       return ret;
 }
 
 static void nvsw_sn2201_destroy_static_devices(struct nvsw_sn2201 *nvsw_sn2201,
index f08ad85683cb0de9ae987a763bb18556d6b4ab1d..bc4013e950ed572018057c9e1ee934235a610beb 100644 (file)
@@ -945,6 +945,8 @@ config PANASONIC_LAPTOP
        tristate "Panasonic Laptop Extras"
        depends on INPUT && ACPI
        depends on BACKLIGHT_CLASS_DEVICE
+       depends on ACPI_VIDEO=n || ACPI_VIDEO
+       depends on SERIO_I8042 || SERIO_I8042 = n
        select INPUT_SPARSEKMAP
        help
          This driver adds support for access to backlight control and hotkeys
index 0d8cb22e30df9081797d1d84d5e25243a3d7ac38..bc7020e9df9e8d40820099d7f19b0bb0c683a934 100644 (file)
@@ -89,6 +89,7 @@ enum hp_wmi_event_ids {
        HPWMI_BACKLIT_KB_BRIGHTNESS     = 0x0D,
        HPWMI_PEAKSHIFT_PERIOD          = 0x0F,
        HPWMI_BATTERY_CHARGE_PERIOD     = 0x10,
+       HPWMI_SANITIZATION_MODE         = 0x17,
 };
 
 /*
@@ -853,6 +854,8 @@ static void hp_wmi_notify(u32 value, void *context)
                break;
        case HPWMI_BATTERY_CHARGE_PERIOD:
                break;
+       case HPWMI_SANITIZATION_MODE:
+               break;
        default:
                pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
                break;
index 3ccb7b71dfb1214225edff3ee7954b34f035197a..abd0c81d62c402645d2878bd5d17dc2f47da7100 100644 (file)
@@ -152,6 +152,10 @@ static bool no_bt_rfkill;
 module_param(no_bt_rfkill, bool, 0444);
 MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
 
+static bool allow_v4_dytc;
+module_param(allow_v4_dytc, bool, 0444);
+MODULE_PARM_DESC(allow_v4_dytc, "Enable DYTC version 4 platform-profile support.");
+
 /*
  * ACPI Helpers
  */
@@ -871,12 +875,18 @@ static void dytc_profile_refresh(struct ideapad_private *priv)
 static const struct dmi_system_id ideapad_dytc_v4_allow_table[] = {
        {
                /* Ideapad 5 Pro 16ACH6 */
-               .ident = "LENOVO 82L5",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "82L5")
                }
        },
+       {
+               /* Ideapad 5 15ITL05 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad 5 15ITL05")
+               }
+       },
        {}
 };
 
@@ -901,13 +911,16 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
 
        dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF;
 
-       if (dytc_version < 5) {
-               if (dytc_version < 4 || !dmi_check_system(ideapad_dytc_v4_allow_table)) {
-                       dev_info(&priv->platform_device->dev,
-                                "DYTC_VERSION is less than 4 or is not allowed: %d\n",
-                                dytc_version);
-                       return -ENODEV;
-               }
+       if (dytc_version < 4) {
+               dev_info(&priv->platform_device->dev, "DYTC_VERSION < 4 is not supported\n");
+               return -ENODEV;
+       }
+
+       if (dytc_version < 5 &&
+           !(allow_v4_dytc || dmi_check_system(ideapad_dytc_v4_allow_table))) {
+               dev_info(&priv->platform_device->dev,
+                        "DYTC_VERSION 4 support may not work. Pass ideapad_laptop.allow_v4_dytc=Y on the kernel commandline to enable\n");
+               return -ENODEV;
        }
 
        priv->dytc = kzalloc(sizeof(*priv->dytc), GFP_KERNEL);
index 40183bda7894ae7890e5042aaa97ae0c2aa8e0d4..a1fe1e0dcf4a53c2e5938de8dd537f3374fb2bc1 100644 (file)
@@ -1911,6 +1911,7 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = {
        X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L,      &icl_reg_map),
        X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE,          &tgl_reg_map),
        X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L,         &tgl_reg_map),
+       X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N,         &tgl_reg_map),
        X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE,           &adl_reg_map),
        X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P,        &tgl_reg_map),
        {}
index 37850d07987d8cb16167de49c5703c27c154ba04..615e39cbbbf198bb50a68c2bba4c9b4fab8f4f46 100644 (file)
  *             - v0.1  start from toshiba_acpi driver written by John Belmonte
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
+#include <linux/acpi.h>
 #include <linux/backlight.h>
 #include <linux/ctype.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/acpi.h>
+#include <linux/i8042.h>
+#include <linux/init.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
-
+#include <linux/seq_file.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <acpi/video.h>
 
 MODULE_AUTHOR("Hiroshi Miura <miura@da-cha.org>");
 MODULE_AUTHOR("David Bronaugh <dbronaugh@linuxboxen.org>");
@@ -241,6 +243,42 @@ struct pcc_acpi {
        struct platform_device  *platform;
 };
 
+/*
+ * On some Panasonic models the volume up / down / mute keys send duplicate
+ * keypress events over the PS/2 kbd interface, filter these out.
+ */
+static bool panasonic_i8042_filter(unsigned char data, unsigned char str,
+                                  struct serio *port)
+{
+       static bool extended;
+
+       if (str & I8042_STR_AUXDATA)
+               return false;
+
+       if (data == 0xe0) {
+               extended = true;
+               return true;
+       } else if (extended) {
+               extended = false;
+
+               switch (data & 0x7f) {
+               case 0x20: /* e0 20 / e0 a0, Volume Mute press / release */
+               case 0x2e: /* e0 2e / e0 ae, Volume Down press / release */
+               case 0x30: /* e0 30 / e0 b0, Volume Up press / release */
+                       return true;
+               default:
+                       /*
+                        * Report the previously filtered e0 before continuing
+                        * with the next non-filtered byte.
+                        */
+                       serio_interrupt(port, 0xe0, 0);
+                       return false;
+               }
+       }
+
+       return false;
+}
+
 /* method access functions */
 static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
 {
@@ -762,6 +800,8 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
        struct input_dev *hotk_input_dev = pcc->input_dev;
        int rc;
        unsigned long long result;
+       unsigned int key;
+       unsigned int updown;
 
        rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
                                   NULL, &result);
@@ -770,20 +810,27 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
                return;
        }
 
+       key = result & 0xf;
+       updown = result & 0x80; /* 0x80 == key down; 0x00 = key up */
+
        /* hack: some firmware sends no key down for sleep / hibernate */
-       if ((result & 0xf) == 0x7 || (result & 0xf) == 0xa) {
-               if (result & 0x80)
+       if (key == 7 || key == 10) {
+               if (updown)
                        sleep_keydown_seen = 1;
                if (!sleep_keydown_seen)
                        sparse_keymap_report_event(hotk_input_dev,
-                                       result & 0xf, 0x80, false);
+                                       key, 0x80, false);
        }
 
-       if ((result & 0xf) == 0x7 || (result & 0xf) == 0x9 || (result & 0xf) == 0xa) {
-               if (!sparse_keymap_report_event(hotk_input_dev,
-                                               result & 0xf, result & 0x80, false))
-                       pr_err("Unknown hotkey event: 0x%04llx\n", result);
-       }
+       /*
+        * Don't report brightness key-presses if they are also reported
+        * by the ACPI video bus.
+        */
+       if ((key == 1 || key == 2) && acpi_video_handles_brightness_key_presses())
+               return;
+
+       if (!sparse_keymap_report_event(hotk_input_dev, key, updown, false))
+               pr_err("Unknown hotkey event: 0x%04llx\n", result);
 }
 
 static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
@@ -997,6 +1044,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
                pcc->platform = NULL;
        }
 
+       i8042_install_filter(panasonic_i8042_filter);
        return 0;
 
 out_platform:
@@ -1020,6 +1068,8 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device)
        if (!device || !pcc)
                return -EINVAL;
 
+       i8042_remove_filter(panasonic_i8042_filter);
+
        if (pcc->platform) {
                device_remove_file(&pcc->platform->dev, &dev_attr_cdpower);
                platform_device_unregister(pcc->platform);
index e6cb4a14cdd4705cb479e4e21b52dbf3d472dda1..a8b383051528517a452b2a13e60f55c908d94f26 100644 (file)
@@ -4529,6 +4529,7 @@ static void thinkpad_acpi_amd_s2idle_restore(void)
        iounmap(addr);
 cleanup_resource:
        release_resource(res);
+       kfree(res);
 }
 
 static struct acpi_s2idle_dev_ops thinkpad_acpi_s2idle_dev_ops = {
@@ -10299,21 +10300,15 @@ static struct ibm_struct proxsensor_driver_data = {
 #define DYTC_DISABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_MMC_BALANCE, 0)
 #define DYTC_ENABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_MMC_BALANCE, 1)
 
-enum dytc_profile_funcmode {
-       DYTC_FUNCMODE_NONE = 0,
-       DYTC_FUNCMODE_MMC,
-       DYTC_FUNCMODE_PSC,
-};
-
-static enum dytc_profile_funcmode dytc_profile_available;
 static enum platform_profile_option dytc_current_profile;
 static atomic_t dytc_ignore_event = ATOMIC_INIT(0);
 static DEFINE_MUTEX(dytc_mutex);
+static int dytc_capabilities;
 static bool dytc_mmc_get_available;
 
 static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile)
 {
-       if (dytc_profile_available == DYTC_FUNCMODE_MMC) {
+       if (dytc_capabilities & BIT(DYTC_FC_MMC)) {
                switch (dytcmode) {
                case DYTC_MODE_MMC_LOWPOWER:
                        *profile = PLATFORM_PROFILE_LOW_POWER;
@@ -10330,7 +10325,7 @@ static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *p
                }
                return 0;
        }
-       if (dytc_profile_available == DYTC_FUNCMODE_PSC) {
+       if (dytc_capabilities & BIT(DYTC_FC_PSC)) {
                switch (dytcmode) {
                case DYTC_MODE_PSC_LOWPOWER:
                        *profile = PLATFORM_PROFILE_LOW_POWER;
@@ -10352,21 +10347,21 @@ static int convert_profile_to_dytc(enum platform_profile_option profile, int *pe
 {
        switch (profile) {
        case PLATFORM_PROFILE_LOW_POWER:
-               if (dytc_profile_available == DYTC_FUNCMODE_MMC)
+               if (dytc_capabilities & BIT(DYTC_FC_MMC))
                        *perfmode = DYTC_MODE_MMC_LOWPOWER;
-               else if (dytc_profile_available == DYTC_FUNCMODE_PSC)
+               else if (dytc_capabilities & BIT(DYTC_FC_PSC))
                        *perfmode = DYTC_MODE_PSC_LOWPOWER;
                break;
        case PLATFORM_PROFILE_BALANCED:
-               if (dytc_profile_available == DYTC_FUNCMODE_MMC)
+               if (dytc_capabilities & BIT(DYTC_FC_MMC))
                        *perfmode = DYTC_MODE_MMC_BALANCE;
-               else if (dytc_profile_available == DYTC_FUNCMODE_PSC)
+               else if (dytc_capabilities & BIT(DYTC_FC_PSC))
                        *perfmode = DYTC_MODE_PSC_BALANCE;
                break;
        case PLATFORM_PROFILE_PERFORMANCE:
-               if (dytc_profile_available == DYTC_FUNCMODE_MMC)
+               if (dytc_capabilities & BIT(DYTC_FC_MMC))
                        *perfmode = DYTC_MODE_MMC_PERFORM;
-               else if (dytc_profile_available == DYTC_FUNCMODE_PSC)
+               else if (dytc_capabilities & BIT(DYTC_FC_PSC))
                        *perfmode = DYTC_MODE_PSC_PERFORM;
                break;
        default: /* Unknown profile */
@@ -10445,7 +10440,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof,
        if (err)
                goto unlock;
 
-       if (dytc_profile_available == DYTC_FUNCMODE_MMC) {
+       if (dytc_capabilities & BIT(DYTC_FC_MMC)) {
                if (profile == PLATFORM_PROFILE_BALANCED) {
                        /*
                         * To get back to balanced mode we need to issue a reset command.
@@ -10464,7 +10459,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof,
                                goto unlock;
                }
        }
-       if (dytc_profile_available == DYTC_FUNCMODE_PSC) {
+       if (dytc_capabilities & BIT(DYTC_FC_PSC)) {
                err = dytc_command(DYTC_SET_COMMAND(DYTC_FUNCTION_PSC, perfmode, 1), &output);
                if (err)
                        goto unlock;
@@ -10483,12 +10478,12 @@ static void dytc_profile_refresh(void)
        int perfmode;
 
        mutex_lock(&dytc_mutex);
-       if (dytc_profile_available == DYTC_FUNCMODE_MMC) {
+       if (dytc_capabilities & BIT(DYTC_FC_MMC)) {
                if (dytc_mmc_get_available)
                        err = dytc_command(DYTC_CMD_MMC_GET, &output);
                else
                        err = dytc_cql_command(DYTC_CMD_GET, &output);
-       } else if (dytc_profile_available == DYTC_FUNCMODE_PSC)
+       } else if (dytc_capabilities & BIT(DYTC_FC_PSC))
                err = dytc_command(DYTC_CMD_GET, &output);
 
        mutex_unlock(&dytc_mutex);
@@ -10517,7 +10512,6 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
        set_bit(PLATFORM_PROFILE_BALANCED, dytc_profile.choices);
        set_bit(PLATFORM_PROFILE_PERFORMANCE, dytc_profile.choices);
 
-       dytc_profile_available = DYTC_FUNCMODE_NONE;
        err = dytc_command(DYTC_CMD_QUERY, &output);
        if (err)
                return err;
@@ -10530,13 +10524,12 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
                return -ENODEV;
 
        /* Check what capabilities are supported */
-       err = dytc_command(DYTC_CMD_FUNC_CAP, &output);
+       err = dytc_command(DYTC_CMD_FUNC_CAP, &dytc_capabilities);
        if (err)
                return err;
 
-       if (output & BIT(DYTC_FC_MMC)) { /* MMC MODE */
-               dytc_profile_available = DYTC_FUNCMODE_MMC;
-
+       if (dytc_capabilities & BIT(DYTC_FC_MMC)) { /* MMC MODE */
+               pr_debug("MMC is supported\n");
                /*
                 * Check if MMC_GET functionality available
                 * Version > 6 and return success from MMC_GET command
@@ -10547,8 +10540,13 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
                        if (!err && ((output & DYTC_ERR_MASK) == DYTC_ERR_SUCCESS))
                                dytc_mmc_get_available = true;
                }
-       } else if (output & BIT(DYTC_FC_PSC)) { /* PSC MODE */
-               dytc_profile_available = DYTC_FUNCMODE_PSC;
+       } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { /* PSC MODE */
+               /* Support for this only works on AMD platforms */
+               if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
+                       dbg_printk(TPACPI_DBG_INIT, "PSC not support on Intel platforms\n");
+                       return -ENODEV;
+               }
+               pr_debug("PSC is supported\n");
        } else {
                dbg_printk(TPACPI_DBG_INIT, "No DYTC support available\n");
                return -ENODEV;
@@ -10574,7 +10572,6 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
 
 static void dytc_profile_exit(void)
 {
-       dytc_profile_available = DYTC_FUNCMODE_NONE;
        platform_profile_remove();
 }
 
index cb24917619589e845a629dd82c75b99f3f5f9564..ae1d6ee382a50e21792f5a47f5433e77a86c7ba0 100644 (file)
@@ -60,7 +60,7 @@ static LIST_HEAD(sclp_reg_list);
 /* List of queued requests. */
 static LIST_HEAD(sclp_req_queue);
 
-/* Data for read and and init requests. */
+/* Data for read and init requests. */
 static struct sclp_req sclp_read_req;
 static struct sclp_req sclp_init_req;
 static void *sclp_read_sccb;
index 97e51c34e6cfbb3f9858da695a28e57378f4b776..161d3b141f0d353db30a43583e1cc544ee994a0d 100644 (file)
@@ -1136,8 +1136,13 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
                        vcdev->err = -EIO;
        }
        virtio_ccw_check_activity(vcdev, activity);
-       /* Interrupts are disabled here */
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
+       /*
+        * Paired with virtio_ccw_synchronize_cbs() and interrupts are
+        * disabled here.
+        */
        read_lock(&vcdev->irq_lock);
+#endif
        for_each_set_bit(i, indicators(vcdev),
                         sizeof(*indicators(vcdev)) * BITS_PER_BYTE) {
                /* The bit clear must happen before the vring kick. */
@@ -1146,7 +1151,9 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
                vq = virtio_ccw_vq_by_ind(vcdev, i);
                vring_interrupt(0, vq);
        }
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
        read_unlock(&vcdev->irq_lock);
+#endif
        if (test_bit(0, indicators2(vcdev))) {
                virtio_config_changed(&vcdev->vdev);
                clear_bit(0, indicators2(vcdev));
index 7d819fc0395e4a08fdc0e05a4db5ce00935f28b8..eb86afb21aabb692756693683c5c2c2bda21c183 100644 (file)
@@ -2782,6 +2782,7 @@ static int slave_configure_v3_hw(struct scsi_device *sdev)
        struct hisi_hba *hisi_hba = shost_priv(shost);
        struct device *dev = hisi_hba->dev;
        int ret = sas_slave_configure(sdev);
+       unsigned int max_sectors;
 
        if (ret)
                return ret;
@@ -2799,6 +2800,12 @@ static int slave_configure_v3_hw(struct scsi_device *sdev)
                }
        }
 
+       /* Set according to IOMMU IOVA caching limit */
+       max_sectors = min_t(size_t, queue_max_hw_sectors(sdev->request_queue),
+                           (PAGE_SIZE * 32) >> SECTOR_SHIFT);
+
+       blk_queue_max_hw_sectors(sdev->request_queue, max_sectors);
+
        return 0;
 }
 
index cd80c7db4073020e4798feec14304f189dbf786c..a9596e7562ea64e8c766742033213aa3842e3971 100644 (file)
@@ -81,6 +81,7 @@ static const struct x86_cpu_id tcc_ids[] __initconst = {
        X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, NULL),
        X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, NULL),
        X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, NULL),
+       X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, NULL),
        {}
 };
 
index 1b6d46b86f810b822cee4dceb966f7871641861f..e85c1d71f4ed28ca9718bcf0515809d383c74ff5 100644 (file)
@@ -1962,6 +1962,8 @@ static void mlx5_vdpa_set_vq_cb(struct vdpa_device *vdev, u16 idx, struct vdpa_c
        struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
 
        ndev->event_cbs[idx] = *cb;
+       if (is_ctrl_vq_idx(mvdev, idx))
+               mvdev->cvq.event_cb = *cb;
 }
 
 static void mlx5_cvq_notify(struct vringh *vring)
@@ -2174,7 +2176,6 @@ static int verify_driver_features(struct mlx5_vdpa_dev *mvdev, u64 features)
 static int setup_virtqueues(struct mlx5_vdpa_dev *mvdev)
 {
        struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
-       struct mlx5_control_vq *cvq = &mvdev->cvq;
        int err;
        int i;
 
@@ -2184,16 +2185,6 @@ static int setup_virtqueues(struct mlx5_vdpa_dev *mvdev)
                        goto err_vq;
        }
 
-       if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) {
-               err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features,
-                                       MLX5_CVQ_MAX_ENT, false,
-                                       (struct vring_desc *)(uintptr_t)cvq->desc_addr,
-                                       (struct vring_avail *)(uintptr_t)cvq->driver_addr,
-                                       (struct vring_used *)(uintptr_t)cvq->device_addr);
-               if (err)
-                       goto err_vq;
-       }
-
        return 0;
 
 err_vq:
@@ -2466,6 +2457,21 @@ static void clear_vqs_ready(struct mlx5_vdpa_net *ndev)
        ndev->mvdev.cvq.ready = false;
 }
 
+static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev)
+{
+       struct mlx5_control_vq *cvq = &mvdev->cvq;
+       int err = 0;
+
+       if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ))
+               err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features,
+                                       MLX5_CVQ_MAX_ENT, false,
+                                       (struct vring_desc *)(uintptr_t)cvq->desc_addr,
+                                       (struct vring_avail *)(uintptr_t)cvq->driver_addr,
+                                       (struct vring_used *)(uintptr_t)cvq->device_addr);
+
+       return err;
+}
+
 static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status)
 {
        struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev);
@@ -2478,6 +2484,11 @@ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status)
 
        if ((status ^ ndev->mvdev.status) & VIRTIO_CONFIG_S_DRIVER_OK) {
                if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
+                       err = setup_cvq_vring(mvdev);
+                       if (err) {
+                               mlx5_vdpa_warn(mvdev, "failed to setup control VQ vring\n");
+                               goto err_setup;
+                       }
                        err = setup_driver(mvdev);
                        if (err) {
                                mlx5_vdpa_warn(mvdev, "failed to setup driver\n");
index 776ad7496f534ab1cf534c1a2224edf954f7c75d..3bc27de58f46b0cfaa01a96e88303cac9c472d64 100644 (file)
@@ -1476,16 +1476,12 @@ static char *vduse_devnode(struct device *dev, umode_t *mode)
        return kasprintf(GFP_KERNEL, "vduse/%s", dev_name(dev));
 }
 
-static void vduse_mgmtdev_release(struct device *dev)
-{
-}
-
-static struct device vduse_mgmtdev = {
-       .init_name = "vduse",
-       .release = vduse_mgmtdev_release,
+struct vduse_mgmt_dev {
+       struct vdpa_mgmt_dev mgmt_dev;
+       struct device dev;
 };
 
-static struct vdpa_mgmt_dev mgmt_dev;
+static struct vduse_mgmt_dev *vduse_mgmt;
 
 static int vduse_dev_init_vdpa(struct vduse_dev *dev, const char *name)
 {
@@ -1510,7 +1506,7 @@ static int vduse_dev_init_vdpa(struct vduse_dev *dev, const char *name)
        }
        set_dma_ops(&vdev->vdpa.dev, &vduse_dev_dma_ops);
        vdev->vdpa.dma_dev = &vdev->vdpa.dev;
-       vdev->vdpa.mdev = &mgmt_dev;
+       vdev->vdpa.mdev = &vduse_mgmt->mgmt_dev;
 
        return 0;
 }
@@ -1556,34 +1552,52 @@ static struct virtio_device_id id_table[] = {
        { 0 },
 };
 
-static struct vdpa_mgmt_dev mgmt_dev = {
-       .device = &vduse_mgmtdev,
-       .id_table = id_table,
-       .ops = &vdpa_dev_mgmtdev_ops,
-};
+static void vduse_mgmtdev_release(struct device *dev)
+{
+       struct vduse_mgmt_dev *mgmt_dev;
+
+       mgmt_dev = container_of(dev, struct vduse_mgmt_dev, dev);
+       kfree(mgmt_dev);
+}
 
 static int vduse_mgmtdev_init(void)
 {
        int ret;
 
-       ret = device_register(&vduse_mgmtdev);
-       if (ret)
+       vduse_mgmt = kzalloc(sizeof(*vduse_mgmt), GFP_KERNEL);
+       if (!vduse_mgmt)
+               return -ENOMEM;
+
+       ret = dev_set_name(&vduse_mgmt->dev, "vduse");
+       if (ret) {
+               kfree(vduse_mgmt);
                return ret;
+       }
 
-       ret = vdpa_mgmtdev_register(&mgmt_dev);
+       vduse_mgmt->dev.release = vduse_mgmtdev_release;
+
+       ret = device_register(&vduse_mgmt->dev);
        if (ret)
-               goto err;
+               goto dev_reg_err;
 
-       return 0;
-err:
-       device_unregister(&vduse_mgmtdev);
+       vduse_mgmt->mgmt_dev.id_table = id_table;
+       vduse_mgmt->mgmt_dev.ops = &vdpa_dev_mgmtdev_ops;
+       vduse_mgmt->mgmt_dev.device = &vduse_mgmt->dev;
+       ret = vdpa_mgmtdev_register(&vduse_mgmt->mgmt_dev);
+       if (ret)
+               device_unregister(&vduse_mgmt->dev);
+
+       return ret;
+
+dev_reg_err:
+       put_device(&vduse_mgmt->dev);
        return ret;
 }
 
 static void vduse_mgmtdev_exit(void)
 {
-       vdpa_mgmtdev_unregister(&mgmt_dev);
-       device_unregister(&vduse_mgmtdev);
+       vdpa_mgmtdev_unregister(&vduse_mgmt->mgmt_dev);
+       device_unregister(&vduse_mgmt->dev);
 }
 
 static int vduse_init(void)
index 5ad2596c6e8a1631a249f7d61df4e8a53f401c64..23dcbfdfa13b19fb6f8ecfddd90769255ddf6902 100644 (file)
@@ -1209,7 +1209,7 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep)
        vhost_dev_stop(&v->vdev);
        vhost_vdpa_free_domain(v);
        vhost_vdpa_config_put(v);
-       vhost_dev_cleanup(&v->vdev);
+       vhost_vdpa_cleanup(v);
        mutex_unlock(&d->mutex);
 
        atomic_dec(&v->opened);
index afa2863670f3454b40431ede34548d906290f2f9..8afc4538558cd74d9f77bbc0c1a5a1e5922f76bc 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/slab.h>
+#include <linux/sysfb.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/vt.h>
@@ -1752,6 +1753,17 @@ int remove_conflicting_framebuffers(struct apertures_struct *a,
                do_free = true;
        }
 
+       /*
+        * If a driver asked to unregister a platform device registered by
+        * sysfb, then can be assumed that this is a driver for a display
+        * that is set up by the system firmware and has a generic driver.
+        *
+        * Drivers for devices that don't have a generic driver will never
+        * ask for this, so let's assume that a real driver for the display
+        * was already probed and prevent sysfb to register devices later.
+        */
+       sysfb_disable();
+
        mutex_lock(&registration_lock);
        do_remove_conflicting_framebuffers(a, name, primary);
        mutex_unlock(&registration_lock);
index a6dc8b5846fe71758be036c44d184ebca72643c3..e1556d2a355ae0147a7f8db1c0a15243800d0c98 100644 (file)
@@ -29,6 +29,19 @@ menuconfig VIRTIO_MENU
 
 if VIRTIO_MENU
 
+config VIRTIO_HARDEN_NOTIFICATION
+        bool "Harden virtio notification"
+        help
+          Enable this to harden the device notifications and suppress
+          those that happen at a time where notifications are illegal.
+
+          Experimental: Note that several drivers still have bugs that
+          may cause crashes or hangs when correct handling of
+          notifications is enforced; depending on the subset of
+          drivers and devices you use, this may or may not work.
+
+          If unsure, say N.
+
 config VIRTIO_PCI
        tristate "PCI driver for virtio devices"
        depends on PCI
index 6bace84ae37ec5674934dca5dc58bf8044738547..7deeed30d1f3a0ec45b87a7cdea2142262390a89 100644 (file)
@@ -219,6 +219,7 @@ static int virtio_features_ok(struct virtio_device *dev)
  * */
 void virtio_reset_device(struct virtio_device *dev)
 {
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
        /*
         * The below virtio_synchronize_cbs() guarantees that any
         * interrupt for this line arriving after
@@ -227,6 +228,7 @@ void virtio_reset_device(struct virtio_device *dev)
         */
        virtio_break_device(dev);
        virtio_synchronize_cbs(dev);
+#endif
 
        dev->config->reset(dev);
 }
index c9bec3813e94949928f24b22322f1b92ba036044..083ff1eb743d3398a09400c48c50683319b7eb85 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/virtio.h>
@@ -556,6 +557,28 @@ static const struct virtio_config_ops virtio_mmio_config_ops = {
        .synchronize_cbs = vm_synchronize_cbs,
 };
 
+#ifdef CONFIG_PM_SLEEP
+static int virtio_mmio_freeze(struct device *dev)
+{
+       struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
+
+       return virtio_device_freeze(&vm_dev->vdev);
+}
+
+static int virtio_mmio_restore(struct device *dev)
+{
+       struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
+
+       if (vm_dev->version == 1)
+               writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
+
+       return virtio_device_restore(&vm_dev->vdev);
+}
+
+static const struct dev_pm_ops virtio_mmio_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(virtio_mmio_freeze, virtio_mmio_restore)
+};
+#endif
 
 static void virtio_mmio_release_dev(struct device *_d)
 {
@@ -799,6 +822,9 @@ static struct platform_driver virtio_mmio_driver = {
                .name   = "virtio-mmio",
                .of_match_table = virtio_mmio_match,
                .acpi_match_table = ACPI_PTR(virtio_mmio_acpi_match),
+#ifdef CONFIG_PM_SLEEP
+               .pm     = &virtio_mmio_pm_ops,
+#endif
        },
 };
 
index b790f30b2b56620e1def1effc366abee5dad4bf9..fa2a9445bb18c8b3799f8da51e520c45f34643a3 100644 (file)
@@ -220,8 +220,6 @@ int vp_modern_probe(struct virtio_pci_modern_device *mdev)
 
        check_offsets();
 
-       mdev->pci_dev = pci_dev;
-
        /* We only own devices >= 0x1000 and <= 0x107f: leave the rest. */
        if (pci_dev->device < 0x1000 || pci_dev->device > 0x107f)
                return -ENODEV;
index 13a7348cedfff01f5d2dab11cbc2cd1b2f067d84..643ca779fcc6354ece2c1d473bf5dbbd81ae97db 100644 (file)
@@ -111,7 +111,12 @@ struct vring_virtqueue {
        /* Number we've added since last sync. */
        unsigned int num_added;
 
-       /* Last used index we've seen. */
+       /* Last used index  we've seen.
+        * for split ring, it just contains last used index
+        * for packed ring:
+        * bits up to VRING_PACKED_EVENT_F_WRAP_CTR include the last used index.
+        * bits from VRING_PACKED_EVENT_F_WRAP_CTR include the used wrap counter.
+        */
        u16 last_used_idx;
 
        /* Hint for event idx: already triggered no need to disable. */
@@ -154,9 +159,6 @@ struct vring_virtqueue {
                        /* Driver ring wrap counter. */
                        bool avail_wrap_counter;
 
-                       /* Device ring wrap counter. */
-                       bool used_wrap_counter;
-
                        /* Avail used flags. */
                        u16 avail_used_flags;
 
@@ -933,7 +935,7 @@ static struct virtqueue *vring_create_virtqueue_split(
        for (; num && vring_size(num, vring_align) > PAGE_SIZE; num /= 2) {
                queue = vring_alloc_queue(vdev, vring_size(num, vring_align),
                                          &dma_addr,
-                                         GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
+                                         GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
                if (queue)
                        break;
                if (!may_reduce_num)
@@ -973,6 +975,15 @@ static struct virtqueue *vring_create_virtqueue_split(
 /*
  * Packed ring specific functions - *_packed().
  */
+static inline bool packed_used_wrap_counter(u16 last_used_idx)
+{
+       return !!(last_used_idx & (1 << VRING_PACKED_EVENT_F_WRAP_CTR));
+}
+
+static inline u16 packed_last_used(u16 last_used_idx)
+{
+       return last_used_idx & ~(-(1 << VRING_PACKED_EVENT_F_WRAP_CTR));
+}
 
 static void vring_unmap_extra_packed(const struct vring_virtqueue *vq,
                                     struct vring_desc_extra *extra)
@@ -1406,8 +1417,14 @@ static inline bool is_used_desc_packed(const struct vring_virtqueue *vq,
 
 static inline bool more_used_packed(const struct vring_virtqueue *vq)
 {
-       return is_used_desc_packed(vq, vq->last_used_idx,
-                       vq->packed.used_wrap_counter);
+       u16 last_used;
+       u16 last_used_idx;
+       bool used_wrap_counter;
+
+       last_used_idx = READ_ONCE(vq->last_used_idx);
+       last_used = packed_last_used(last_used_idx);
+       used_wrap_counter = packed_used_wrap_counter(last_used_idx);
+       return is_used_desc_packed(vq, last_used, used_wrap_counter);
 }
 
 static void *virtqueue_get_buf_ctx_packed(struct virtqueue *_vq,
@@ -1415,7 +1432,8 @@ static void *virtqueue_get_buf_ctx_packed(struct virtqueue *_vq,
                                          void **ctx)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
-       u16 last_used, id;
+       u16 last_used, id, last_used_idx;
+       bool used_wrap_counter;
        void *ret;
 
        START_USE(vq);
@@ -1434,7 +1452,9 @@ static void *virtqueue_get_buf_ctx_packed(struct virtqueue *_vq,
        /* Only get used elements after they have been exposed by host. */
        virtio_rmb(vq->weak_barriers);
 
-       last_used = vq->last_used_idx;
+       last_used_idx = READ_ONCE(vq->last_used_idx);
+       used_wrap_counter = packed_used_wrap_counter(last_used_idx);
+       last_used = packed_last_used(last_used_idx);
        id = le16_to_cpu(vq->packed.vring.desc[last_used].id);
        *len = le32_to_cpu(vq->packed.vring.desc[last_used].len);
 
@@ -1451,12 +1471,15 @@ static void *virtqueue_get_buf_ctx_packed(struct virtqueue *_vq,
        ret = vq->packed.desc_state[id].data;
        detach_buf_packed(vq, id, ctx);
 
-       vq->last_used_idx += vq->packed.desc_state[id].num;
-       if (unlikely(vq->last_used_idx >= vq->packed.vring.num)) {
-               vq->last_used_idx -= vq->packed.vring.num;
-               vq->packed.used_wrap_counter ^= 1;
+       last_used += vq->packed.desc_state[id].num;
+       if (unlikely(last_used >= vq->packed.vring.num)) {
+               last_used -= vq->packed.vring.num;
+               used_wrap_counter ^= 1;
        }
 
+       last_used = (last_used | (used_wrap_counter << VRING_PACKED_EVENT_F_WRAP_CTR));
+       WRITE_ONCE(vq->last_used_idx, last_used);
+
        /*
         * If we expect an interrupt for the next entry, tell host
         * by writing event index and flush out the write before
@@ -1465,9 +1488,7 @@ static void *virtqueue_get_buf_ctx_packed(struct virtqueue *_vq,
        if (vq->packed.event_flags_shadow == VRING_PACKED_EVENT_FLAG_DESC)
                virtio_store_mb(vq->weak_barriers,
                                &vq->packed.vring.driver->off_wrap,
-                               cpu_to_le16(vq->last_used_idx |
-                                       (vq->packed.used_wrap_counter <<
-                                        VRING_PACKED_EVENT_F_WRAP_CTR)));
+                               cpu_to_le16(vq->last_used_idx));
 
        LAST_ADD_TIME_INVALID(vq);
 
@@ -1499,9 +1520,7 @@ static unsigned int virtqueue_enable_cb_prepare_packed(struct virtqueue *_vq)
 
        if (vq->event) {
                vq->packed.vring.driver->off_wrap =
-                       cpu_to_le16(vq->last_used_idx |
-                               (vq->packed.used_wrap_counter <<
-                                VRING_PACKED_EVENT_F_WRAP_CTR));
+                       cpu_to_le16(vq->last_used_idx);
                /*
                 * We need to update event offset and event wrap
                 * counter first before updating event flags.
@@ -1518,8 +1537,7 @@ static unsigned int virtqueue_enable_cb_prepare_packed(struct virtqueue *_vq)
        }
 
        END_USE(vq);
-       return vq->last_used_idx | ((u16)vq->packed.used_wrap_counter <<
-                       VRING_PACKED_EVENT_F_WRAP_CTR);
+       return vq->last_used_idx;
 }
 
 static bool virtqueue_poll_packed(struct virtqueue *_vq, u16 off_wrap)
@@ -1537,7 +1555,7 @@ static bool virtqueue_poll_packed(struct virtqueue *_vq, u16 off_wrap)
 static bool virtqueue_enable_cb_delayed_packed(struct virtqueue *_vq)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
-       u16 used_idx, wrap_counter;
+       u16 used_idx, wrap_counter, last_used_idx;
        u16 bufs;
 
        START_USE(vq);
@@ -1550,9 +1568,10 @@ static bool virtqueue_enable_cb_delayed_packed(struct virtqueue *_vq)
        if (vq->event) {
                /* TODO: tune this threshold */
                bufs = (vq->packed.vring.num - vq->vq.num_free) * 3 / 4;
-               wrap_counter = vq->packed.used_wrap_counter;
+               last_used_idx = READ_ONCE(vq->last_used_idx);
+               wrap_counter = packed_used_wrap_counter(last_used_idx);
 
-               used_idx = vq->last_used_idx + bufs;
+               used_idx = packed_last_used(last_used_idx) + bufs;
                if (used_idx >= vq->packed.vring.num) {
                        used_idx -= vq->packed.vring.num;
                        wrap_counter ^= 1;
@@ -1582,9 +1601,10 @@ static bool virtqueue_enable_cb_delayed_packed(struct virtqueue *_vq)
         */
        virtio_mb(vq->weak_barriers);
 
-       if (is_used_desc_packed(vq,
-                               vq->last_used_idx,
-                               vq->packed.used_wrap_counter)) {
+       last_used_idx = READ_ONCE(vq->last_used_idx);
+       wrap_counter = packed_used_wrap_counter(last_used_idx);
+       used_idx = packed_last_used(last_used_idx);
+       if (is_used_desc_packed(vq, used_idx, wrap_counter)) {
                END_USE(vq);
                return false;
        }
@@ -1688,8 +1708,12 @@ static struct virtqueue *vring_create_virtqueue_packed(
        vq->we_own_ring = true;
        vq->notify = notify;
        vq->weak_barriers = weak_barriers;
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
        vq->broken = true;
-       vq->last_used_idx = 0;
+#else
+       vq->broken = false;
+#endif
+       vq->last_used_idx = 0 | (1 << VRING_PACKED_EVENT_F_WRAP_CTR);
        vq->event_triggered = false;
        vq->num_added = 0;
        vq->packed_ring = true;
@@ -1720,7 +1744,6 @@ static struct virtqueue *vring_create_virtqueue_packed(
 
        vq->packed.next_avail_idx = 0;
        vq->packed.avail_wrap_counter = 1;
-       vq->packed.used_wrap_counter = 1;
        vq->packed.event_flags_shadow = 0;
        vq->packed.avail_used_flags = 1 << VRING_PACKED_DESC_F_AVAIL;
 
@@ -2135,9 +2158,13 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
        }
 
        if (unlikely(vq->broken)) {
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
                dev_warn_once(&vq->vq.vdev->dev,
                              "virtio vring IRQ raised before DRIVER_OK");
                return IRQ_NONE;
+#else
+               return IRQ_HANDLED;
+#endif
        }
 
        /* Just a hint for performance: so it's ok that this can be racy! */
@@ -2180,7 +2207,11 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
        vq->we_own_ring = false;
        vq->notify = notify;
        vq->weak_barriers = weak_barriers;
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
        vq->broken = true;
+#else
+       vq->broken = false;
+#endif
        vq->last_used_idx = 0;
        vq->event_triggered = false;
        vq->num_added = 0;
index 38c930384d417dc33ab527546b46fef858d9268d..ac8fd5e7f5405f345fe12a7276819f3a513309fe 100644 (file)
@@ -4377,6 +4377,7 @@ static void flush_dirty_session_caps(struct ceph_mds_session *s)
                ihold(inode);
                dout("flush_dirty_caps %llx.%llx\n", ceph_vinop(inode));
                spin_unlock(&mdsc->cap_dirty_lock);
+               ceph_wait_on_async_create(inode);
                ceph_check_caps(ci, CHECK_CAPS_FLUSH, NULL);
                iput(inode);
                spin_lock(&mdsc->cap_dirty_lock);
index 5ff2cdb425bc4c4c3c71e221ee771e99d9ba5702..0d491ad15b66ad92eb12b480331b32e841675281 100644 (file)
@@ -1183,6 +1183,7 @@ static const struct io_op_def io_op_defs[] = {
                .unbound_nonreg_file    = 1,
                .pollout                = 1,
                .needs_async_setup      = 1,
+               .ioprio                 = 1,
                .async_size             = sizeof(struct io_async_msghdr),
        },
        [IORING_OP_RECVMSG] = {
@@ -1191,6 +1192,7 @@ static const struct io_op_def io_op_defs[] = {
                .pollin                 = 1,
                .buffer_select          = 1,
                .needs_async_setup      = 1,
+               .ioprio                 = 1,
                .async_size             = sizeof(struct io_async_msghdr),
        },
        [IORING_OP_TIMEOUT] = {
@@ -1266,6 +1268,7 @@ static const struct io_op_def io_op_defs[] = {
                .unbound_nonreg_file    = 1,
                .pollout                = 1,
                .audit_skip             = 1,
+               .ioprio                 = 1,
        },
        [IORING_OP_RECV] = {
                .needs_file             = 1,
@@ -1273,6 +1276,7 @@ static const struct io_op_def io_op_defs[] = {
                .pollin                 = 1,
                .buffer_select          = 1,
                .audit_skip             = 1,
+               .ioprio                 = 1,
        },
        [IORING_OP_OPENAT2] = {
        },
@@ -4314,18 +4318,19 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags)
                if (unlikely(ret < 0))
                        return ret;
        } else {
+               rw = req->async_data;
+               s = &rw->s;
+
                /*
                 * Safe and required to re-import if we're using provided
                 * buffers, as we dropped the selected one before retry.
                 */
-               if (req->flags & REQ_F_BUFFER_SELECT) {
+               if (io_do_buffer_select(req)) {
                        ret = io_import_iovec(READ, req, &iovec, s, issue_flags);
                        if (unlikely(ret < 0))
                                return ret;
                }
 
-               rw = req->async_data;
-               s = &rw->s;
                /*
                 * We come here from an earlier attempt, restore our state to
                 * match in case it doesn't. It's cheap enough that we don't
@@ -6075,12 +6080,12 @@ static int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_sr_msg *sr = &req->sr_msg;
 
-       if (unlikely(sqe->file_index))
+       if (unlikely(sqe->file_index || sqe->addr2))
                return -EINVAL;
 
        sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr));
        sr->len = READ_ONCE(sqe->len);
-       sr->flags = READ_ONCE(sqe->addr2);
+       sr->flags = READ_ONCE(sqe->ioprio);
        if (sr->flags & ~IORING_RECVSEND_POLL_FIRST)
                return -EINVAL;
        sr->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL;
@@ -6311,12 +6316,12 @@ static int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_sr_msg *sr = &req->sr_msg;
 
-       if (unlikely(sqe->file_index))
+       if (unlikely(sqe->file_index || sqe->addr2))
                return -EINVAL;
 
        sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr));
        sr->len = READ_ONCE(sqe->len);
-       sr->flags = READ_ONCE(sqe->addr2);
+       sr->flags = READ_ONCE(sqe->ioprio);
        if (sr->flags & ~IORING_RECVSEND_POLL_FIRST)
                return -EINVAL;
        sr->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL;
index e6f4ccc12f494c57387c06ae6e289067d48e7e77..353f047e783cad7b843f6329eecab2c461163656 100644 (file)
@@ -6490,6 +6490,7 @@ int smb2_write(struct ksmbd_work *work)
                goto out;
        }
 
+       ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags));
        if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
                writethrough = true;
 
@@ -6505,10 +6506,6 @@ int smb2_write(struct ksmbd_work *work)
                data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
                                    le16_to_cpu(req->DataOffset));
 
-               ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags));
-               if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
-                       writethrough = true;
-
                ksmbd_debug(SMB, "filename %pd, offset %lld, len %zu\n",
                            fp->filp->f_path.dentry, offset, length);
                err = ksmbd_vfs_write(work, fp, data_buf, length, &offset,
@@ -7703,7 +7700,7 @@ int smb2_ioctl(struct ksmbd_work *work)
        {
                struct file_zero_data_information *zero_data;
                struct ksmbd_file *fp;
-               loff_t off, len;
+               loff_t off, len, bfz;
 
                if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
                        ksmbd_debug(SMB,
@@ -7720,19 +7717,26 @@ int smb2_ioctl(struct ksmbd_work *work)
                zero_data =
                        (struct file_zero_data_information *)&req->Buffer[0];
 
-               fp = ksmbd_lookup_fd_fast(work, id);
-               if (!fp) {
-                       ret = -ENOENT;
+               off = le64_to_cpu(zero_data->FileOffset);
+               bfz = le64_to_cpu(zero_data->BeyondFinalZero);
+               if (off > bfz) {
+                       ret = -EINVAL;
                        goto out;
                }
 
-               off = le64_to_cpu(zero_data->FileOffset);
-               len = le64_to_cpu(zero_data->BeyondFinalZero) - off;
+               len = bfz - off;
+               if (len) {
+                       fp = ksmbd_lookup_fd_fast(work, id);
+                       if (!fp) {
+                               ret = -ENOENT;
+                               goto out;
+                       }
 
-               ret = ksmbd_vfs_zero_data(work, fp, off, len);
-               ksmbd_fd_put(work, fp);
-               if (ret < 0)
-                       goto out;
+                       ret = ksmbd_vfs_zero_data(work, fp, off, len);
+                       ksmbd_fd_put(work, fp);
+                       if (ret < 0)
+                               goto out;
+               }
                break;
        }
        case FSCTL_QUERY_ALLOCATED_RANGES:
@@ -7806,14 +7810,24 @@ int smb2_ioctl(struct ksmbd_work *work)
                src_off = le64_to_cpu(dup_ext->SourceFileOffset);
                dst_off = le64_to_cpu(dup_ext->TargetFileOffset);
                length = le64_to_cpu(dup_ext->ByteCount);
-               cloned = vfs_clone_file_range(fp_in->filp, src_off, fp_out->filp,
-                                             dst_off, length, 0);
+               /*
+                * XXX: It is not clear if FSCTL_DUPLICATE_EXTENTS_TO_FILE
+                * should fall back to vfs_copy_file_range().  This could be
+                * beneficial when re-exporting nfs/smb mount, but note that
+                * this can result in partial copy that returns an error status.
+                * If/when FSCTL_DUPLICATE_EXTENTS_TO_FILE_EX is implemented,
+                * fall back to vfs_copy_file_range(), should be avoided when
+                * the flag DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC is set.
+                */
+               cloned = vfs_clone_file_range(fp_in->filp, src_off,
+                                             fp_out->filp, dst_off, length, 0);
                if (cloned == -EXDEV || cloned == -EOPNOTSUPP) {
                        ret = -EOPNOTSUPP;
                        goto dup_ext_out;
                } else if (cloned != length) {
                        cloned = vfs_copy_file_range(fp_in->filp, src_off,
-                                                    fp_out->filp, dst_off, length, 0);
+                                                    fp_out->filp, dst_off,
+                                                    length, 0);
                        if (cloned != length) {
                                if (cloned < 0)
                                        ret = cloned;
index d035e060c2f0a9495579f96b8e53e6cd91493d9f..35b55ee94fe5496c18a8bb55503c2a2a2acd9cc1 100644 (file)
@@ -5,16 +5,6 @@
  *
  *   Author(s): Long Li <longli@microsoft.com>,
  *             Hyunchul Lee <hyc.lee@gmail.com>
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
  */
 
 #define SUBMOD_NAME    "smb_direct"
index 8fef9de787d34f7e64a235c9096645214290a7b3..143bba4e4db814a6f44cb55db0fe40fd9042a8a3 100644 (file)
@@ -230,7 +230,7 @@ static int ksmbd_kthread_fn(void *p)
                        break;
                }
                ret = kernel_accept(iface->ksmbd_socket, &client_sk,
-                                   O_NONBLOCK);
+                                   SOCK_NONBLOCK);
                mutex_unlock(&iface->sock_release_lock);
                if (ret) {
                        if (ret == -EAGAIN)
index dcdd07c6efffd58250dd37868de3a7acbb2a5476..05efcdf7a4a73edbed63c9903856951ff061f2a1 100644 (file)
@@ -1015,7 +1015,9 @@ int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
                                     FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
                                     off, len);
 
-       return vfs_fallocate(fp->filp, FALLOC_FL_ZERO_RANGE, off, len);
+       return vfs_fallocate(fp->filp,
+                            FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE,
+                            off, len);
 }
 
 int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
@@ -1046,7 +1048,7 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
        *out_count = 0;
        end = start + length;
        while (start < end && *out_count < in_count) {
-               extent_start = f->f_op->llseek(f, start, SEEK_DATA);
+               extent_start = vfs_llseek(f, start, SEEK_DATA);
                if (extent_start < 0) {
                        if (extent_start != -ENXIO)
                                ret = (int)extent_start;
@@ -1056,7 +1058,7 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
                if (extent_start >= end)
                        break;
 
-               extent_end = f->f_op->llseek(f, extent_start, SEEK_HOLE);
+               extent_end = vfs_llseek(f, extent_start, SEEK_HOLE);
                if (extent_end < 0) {
                        if (extent_end != -ENXIO)
                                ret = (int)extent_end;
@@ -1777,6 +1779,10 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
 
                ret = vfs_copy_file_range(src_fp->filp, src_off,
                                          dst_fp->filp, dst_off, len, 0);
+               if (ret == -EOPNOTSUPP || ret == -EXDEV)
+                       ret = generic_copy_file_range(src_fp->filp, src_off,
+                                                     dst_fp->filp, dst_off,
+                                                     len, 0);
                if (ret < 0)
                        return ret;
 
index c0fdcf8c00329b297063e69341017b980e7b704b..bb0e84a46d61a38848e0c94c36a9e602b5bb6e19 100644 (file)
@@ -4012,22 +4012,29 @@ static int _nfs4_discover_trunking(struct nfs_server *server,
        }
 
        page = alloc_page(GFP_KERNEL);
+       if (!page)
+               return -ENOMEM;
        locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
-       if (page == NULL || locations == NULL)
-               goto out;
+       if (!locations)
+               goto out_free;
+       locations->fattr = nfs_alloc_fattr();
+       if (!locations->fattr)
+               goto out_free_2;
 
        status = nfs4_proc_get_locations(server, fhandle, locations, page,
                                         cred);
        if (status)
-               goto out;
+               goto out_free_3;
 
        for (i = 0; i < locations->nlocations; i++)
                test_fs_location_for_trunking(&locations->locations[i], clp,
                                              server);
-out:
-       if (page)
-               __free_page(page);
+out_free_3:
+       kfree(locations->fattr);
+out_free_2:
        kfree(locations);
+out_free:
+       __free_page(page);
        return status;
 }
 
index 2540b35ec1870793d067dd915f4d37c834c0b7a9..9bab3e9c702a47153703c7f7ae62176fed75fe6f 100644 (file)
@@ -2753,5 +2753,6 @@ again:
                goto again;
 
        nfs_put_client(clp);
+       module_put_and_kthread_exit(0);
        return 0;
 }
index 840e3af63a6f1a352f5179c6df8e10cc81ed87f7..d79db56475d42fa13990718f04edd022bd06503a 100644 (file)
@@ -577,6 +577,7 @@ out_err:
 ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
                             u64 dst_pos, u64 count)
 {
+       ssize_t ret;
 
        /*
         * Limit copy to 4MB to prevent indefinitely blocking an nfsd
@@ -587,7 +588,12 @@ ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
         * limit like this and pipeline multiple COPY requests.
         */
        count = min_t(u64, count, 1 << 22);
-       return vfs_copy_file_range(src, src_pos, dst, dst_pos, count, 0);
+       ret = vfs_copy_file_range(src, src_pos, dst, dst_pos, count, 0);
+
+       if (ret == -EOPNOTSUPP || ret == -EXDEV)
+               ret = generic_copy_file_range(src, src_pos, dst, dst_pos,
+                                             count, 0);
+       return ret;
 }
 
 __be32 nfsd4_vfs_fallocate(struct svc_rqst *rqstp, struct svc_fh *fhp,
@@ -1173,6 +1179,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset,
                        nfsd_copy_write_verifier(verf, nn);
                        err2 = filemap_check_wb_err(nf->nf_file->f_mapping,
                                                    since);
+                       err = nfserrno(err2);
                        break;
                case -EINVAL:
                        err = nfserr_notsupp;
@@ -1180,8 +1187,8 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset,
                default:
                        nfsd_reset_write_verifier(nn);
                        trace_nfsd_writeverf_reset(nn, rqstp, err2);
+                       err = nfserrno(err2);
                }
-               err = nfserrno(err2);
        } else
                nfsd_copy_write_verifier(verf, nn);
 
index c2255b440df9f7d741ba52990a3274bcd9b93c8b..b08ce0d821a7f6c2839fdd9386f3607d69c7641e 100644 (file)
@@ -1513,8 +1513,15 @@ static int fanotify_test_fid(struct dentry *dentry)
        return 0;
 }
 
-static int fanotify_events_supported(struct path *path, __u64 mask)
+static int fanotify_events_supported(struct fsnotify_group *group,
+                                    struct path *path, __u64 mask,
+                                    unsigned int flags)
 {
+       unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
+       /* Strict validation of events in non-dir inode mask with v5.17+ APIs */
+       bool strict_dir_events = FAN_GROUP_FLAG(group, FAN_REPORT_TARGET_FID) ||
+                                (mask & FAN_RENAME);
+
        /*
         * Some filesystems such as 'proc' acquire unusual locks when opening
         * files. For them fanotify permission events have high chances of
@@ -1526,6 +1533,16 @@ static int fanotify_events_supported(struct path *path, __u64 mask)
        if (mask & FANOTIFY_PERM_EVENTS &&
            path->mnt->mnt_sb->s_type->fs_flags & FS_DISALLOW_NOTIFY_PERM)
                return -EINVAL;
+
+       /*
+        * We shouldn't have allowed setting dirent events and the directory
+        * flags FAN_ONDIR and FAN_EVENT_ON_CHILD in mask of non-dir inode,
+        * but because we always allowed it, error only when using new APIs.
+        */
+       if (strict_dir_events && mark_type == FAN_MARK_INODE &&
+           !d_is_dir(path->dentry) && (mask & FANOTIFY_DIRONLY_EVENT_BITS))
+               return -ENOTDIR;
+
        return 0;
 }
 
@@ -1672,7 +1689,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
                goto fput_and_out;
 
        if (flags & FAN_MARK_ADD) {
-               ret = fanotify_events_supported(&path, mask);
+               ret = fanotify_events_supported(group, &path, mask, flags);
                if (ret)
                        goto path_put_and_out;
        }
@@ -1695,19 +1712,6 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
        else
                mnt = path.mnt;
 
-       /*
-        * FAN_RENAME is not allowed on non-dir (for now).
-        * We shouldn't have allowed setting any dirent events in mask of
-        * non-dir, but because we always allowed it, error only if group
-        * was initialized with the new flag FAN_REPORT_TARGET_FID.
-        */
-       ret = -ENOTDIR;
-       if (inode && !S_ISDIR(inode->i_mode) &&
-           ((mask & FAN_RENAME) ||
-            ((mask & FANOTIFY_DIRENT_EVENTS) &&
-             FAN_GROUP_FLAG(group, FAN_REPORT_TARGET_FID))))
-               goto path_put_and_out;
-
        /* Mask out FAN_EVENT_ON_CHILD flag for sb/mount/non-dir marks */
        if (mnt || !S_ISDIR(inode->i_mode)) {
                mask &= ~FAN_EVENT_ON_CHILD;
index b1b1cdfee9d39a85c777166688119bdc71026a09..e0777eefd84650debb0bed304401f81d8ccb1c8e 100644 (file)
@@ -1397,28 +1397,6 @@ ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in,
 }
 EXPORT_SYMBOL(generic_copy_file_range);
 
-static ssize_t do_copy_file_range(struct file *file_in, loff_t pos_in,
-                                 struct file *file_out, loff_t pos_out,
-                                 size_t len, unsigned int flags)
-{
-       /*
-        * Although we now allow filesystems to handle cross sb copy, passing
-        * a file of the wrong filesystem type to filesystem driver can result
-        * in an attempt to dereference the wrong type of ->private_data, so
-        * avoid doing that until we really have a good reason.  NFS defines
-        * several different file_system_type structures, but they all end up
-        * using the same ->copy_file_range() function pointer.
-        */
-       if (file_out->f_op->copy_file_range &&
-           file_out->f_op->copy_file_range == file_in->f_op->copy_file_range)
-               return file_out->f_op->copy_file_range(file_in, pos_in,
-                                                      file_out, pos_out,
-                                                      len, flags);
-
-       return generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
-                                      flags);
-}
-
 /*
  * Performs necessary checks before doing a file copy
  *
@@ -1440,6 +1418,24 @@ static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,
        if (ret)
                return ret;
 
+       /*
+        * We allow some filesystems to handle cross sb copy, but passing
+        * a file of the wrong filesystem type to filesystem driver can result
+        * in an attempt to dereference the wrong type of ->private_data, so
+        * avoid doing that until we really have a good reason.
+        *
+        * nfs and cifs define several different file_system_type structures
+        * and several different sets of file_operations, but they all end up
+        * using the same ->copy_file_range() function pointer.
+        */
+       if (file_out->f_op->copy_file_range) {
+               if (file_in->f_op->copy_file_range !=
+                   file_out->f_op->copy_file_range)
+                       return -EXDEV;
+       } else if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) {
+               return -EXDEV;
+       }
+
        /* Don't touch certain kinds of inodes */
        if (IS_IMMUTABLE(inode_out))
                return -EPERM;
@@ -1505,26 +1501,41 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
        file_start_write(file_out);
 
        /*
-        * Try cloning first, this is supported by more file systems, and
-        * more efficient if both clone and copy are supported (e.g. NFS).
+        * Cloning is supported by more file systems, so we implement copy on
+        * same sb using clone, but for filesystems where both clone and copy
+        * are supported (e.g. nfs,cifs), we only call the copy method.
         */
+       if (file_out->f_op->copy_file_range) {
+               ret = file_out->f_op->copy_file_range(file_in, pos_in,
+                                                     file_out, pos_out,
+                                                     len, flags);
+               goto done;
+       }
+
        if (file_in->f_op->remap_file_range &&
            file_inode(file_in)->i_sb == file_inode(file_out)->i_sb) {
-               loff_t cloned;
-
-               cloned = file_in->f_op->remap_file_range(file_in, pos_in,
+               ret = file_in->f_op->remap_file_range(file_in, pos_in,
                                file_out, pos_out,
                                min_t(loff_t, MAX_RW_COUNT, len),
                                REMAP_FILE_CAN_SHORTEN);
-               if (cloned > 0) {
-                       ret = cloned;
+               if (ret > 0)
                        goto done;
-               }
        }
 
-       ret = do_copy_file_range(file_in, pos_in, file_out, pos_out, len,
-                               flags);
-       WARN_ON_ONCE(ret == -EOPNOTSUPP);
+       /*
+        * We can get here for same sb copy of filesystems that do not implement
+        * ->copy_file_range() in case filesystem does not support clone or in
+        * case filesystem supports clone but rejected the clone request (e.g.
+        * because it was not block aligned).
+        *
+        * In both cases, fall back to kernel copy so we are able to maintain a
+        * consistent story about which filesystems support copy_file_range()
+        * and which filesystems do not, that will allow userspace tools to
+        * make consistent desicions w.r.t using copy_file_range().
+        */
+       ret = generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
+                                     flags);
+
 done:
        if (ret > 0) {
                fsnotify_access(file_in);
index 1824f61621a24496ccffc83a642b2c43a19a81ad..224649a76cbbb84e8852a1917e45c123f231789d 100644 (file)
@@ -50,7 +50,7 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
 STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
 STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
 STATIC int xfs_attr_leaf_hasname(struct xfs_da_args *args, struct xfs_buf **bp);
-STATIC int xfs_attr_leaf_try_add(struct xfs_da_args *args, struct xfs_buf *bp);
+STATIC int xfs_attr_leaf_try_add(struct xfs_da_args *args);
 
 /*
  * Internal routines when attribute list is more than one block.
@@ -393,16 +393,10 @@ xfs_attr_sf_addname(
         * It won't fit in the shortform, transform to a leaf block.  GROT:
         * another possible req'mt for a double-split btree op.
         */
-       error = xfs_attr_shortform_to_leaf(args, &attr->xattri_leaf_bp);
+       error = xfs_attr_shortform_to_leaf(args);
        if (error)
                return error;
 
-       /*
-        * Prevent the leaf buffer from being unlocked so that a concurrent AIL
-        * push cannot grab the half-baked leaf buffer and run into problems
-        * with the write verifier.
-        */
-       xfs_trans_bhold(args->trans, attr->xattri_leaf_bp);
        attr->xattri_dela_state = XFS_DAS_LEAF_ADD;
 out:
        trace_xfs_attr_sf_addname_return(attr->xattri_dela_state, args->dp);
@@ -447,11 +441,9 @@ xfs_attr_leaf_addname(
 
        /*
         * Use the leaf buffer we may already hold locked as a result of
-        * a sf-to-leaf conversion. The held buffer is no longer valid
-        * after this call, regardless of the result.
+        * a sf-to-leaf conversion.
         */
-       error = xfs_attr_leaf_try_add(args, attr->xattri_leaf_bp);
-       attr->xattri_leaf_bp = NULL;
+       error = xfs_attr_leaf_try_add(args);
 
        if (error == -ENOSPC) {
                error = xfs_attr3_leaf_to_node(args);
@@ -497,8 +489,6 @@ xfs_attr_node_addname(
        struct xfs_da_args      *args = attr->xattri_da_args;
        int                     error;
 
-       ASSERT(!attr->xattri_leaf_bp);
-
        error = xfs_attr_node_addname_find_attr(attr);
        if (error)
                return error;
@@ -1215,24 +1205,14 @@ xfs_attr_restore_rmt_blk(
  */
 STATIC int
 xfs_attr_leaf_try_add(
-       struct xfs_da_args      *args,
-       struct xfs_buf          *bp)
+       struct xfs_da_args      *args)
 {
+       struct xfs_buf          *bp;
        int                     error;
 
-       /*
-        * If the caller provided a buffer to us, it is locked and held in
-        * the transaction because it just did a shortform to leaf conversion.
-        * Hence we don't need to read it again. Otherwise read in the leaf
-        * buffer.
-        */
-       if (bp) {
-               xfs_trans_bhold_release(args->trans, bp);
-       } else {
-               error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
-               if (error)
-                       return error;
-       }
+       error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
+       if (error)
+               return error;
 
        /*
         * Look up the xattr name to set the insertion point for the new xattr.
index b4a2fc77017e0608b333c177e480addef844a48a..dfb47fa63c6d52785f0566056ad98435efc57b53 100644 (file)
@@ -515,11 +515,6 @@ struct xfs_attr_intent {
         */
        struct xfs_attri_log_nameval    *xattri_nameval;
 
-       /*
-        * Used by xfs_attr_set to hold a leaf buffer across a transaction roll
-        */
-       struct xfs_buf                  *xattri_leaf_bp;
-
        /* Used to keep track of current state of delayed operation */
        enum xfs_delattr_state          xattri_dela_state;
 
index 37e7c33f62839929d73c43b0ce330454e50b4eaf..8f47396f8dd23bbfbe8cd93a25a9a9f60e724228 100644 (file)
@@ -289,6 +289,23 @@ xfs_attr3_leaf_verify_entry(
        return NULL;
 }
 
+/*
+ * Validate an attribute leaf block.
+ *
+ * Empty leaf blocks can occur under the following circumstances:
+ *
+ * 1. setxattr adds a new extended attribute to a file;
+ * 2. The file has zero existing attributes;
+ * 3. The attribute is too large to fit in the attribute fork;
+ * 4. The attribute is small enough to fit in a leaf block;
+ * 5. A log flush occurs after committing the transaction that creates
+ *    the (empty) leaf block; and
+ * 6. The filesystem goes down after the log flush but before the new
+ *    attribute can be committed to the leaf block.
+ *
+ * Hence we need to ensure that we don't fail the validation purely
+ * because the leaf is empty.
+ */
 static xfs_failaddr_t
 xfs_attr3_leaf_verify(
        struct xfs_buf                  *bp)
@@ -310,15 +327,6 @@ xfs_attr3_leaf_verify(
        if (fa)
                return fa;
 
-       /*
-        * Empty leaf blocks should never occur;  they imply the existence of a
-        * software bug that needs fixing. xfs_repair also flags them as a
-        * corruption that needs fixing, so we should never let these go to
-        * disk.
-        */
-       if (ichdr.count == 0)
-               return __this_address;
-
        /*
         * firstused is the block offset of the first name info structure.
         * Make sure it doesn't go off the block or crash into the header.
@@ -922,14 +930,10 @@ xfs_attr_shortform_getvalue(
        return -ENOATTR;
 }
 
-/*
- * Convert from using the shortform to the leaf.  On success, return the
- * buffer so that we can keep it locked until we're totally done with it.
- */
+/* Convert from using the shortform to the leaf format. */
 int
 xfs_attr_shortform_to_leaf(
-       struct xfs_da_args              *args,
-       struct xfs_buf                  **leaf_bp)
+       struct xfs_da_args              *args)
 {
        struct xfs_inode                *dp;
        struct xfs_attr_shortform       *sf;
@@ -991,7 +995,6 @@ xfs_attr_shortform_to_leaf(
                sfe = xfs_attr_sf_nextentry(sfe);
        }
        error = 0;
-       *leaf_bp = bp;
 out:
        kmem_free(tmpbuffer);
        return error;
index efa757f1e912c7ac8ba642c6a9586c02479d1064..368f4d9fa1d596a43649c307676597b05a74e656 100644 (file)
@@ -49,8 +49,7 @@ void  xfs_attr_shortform_create(struct xfs_da_args *args);
 void   xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff);
 int    xfs_attr_shortform_lookup(struct xfs_da_args *args);
 int    xfs_attr_shortform_getvalue(struct xfs_da_args *args);
-int    xfs_attr_shortform_to_leaf(struct xfs_da_args *args,
-                       struct xfs_buf **leaf_bp);
+int    xfs_attr_shortform_to_leaf(struct xfs_da_args *args);
 int    xfs_attr_sf_removename(struct xfs_da_args *args);
 int    xfs_attr_sf_findname(struct xfs_da_args *args,
                             struct xfs_attr_sf_entry **sfep,
index 135d441334773c18abf238ce12f02cef105aae25..5077a7ad56460f78cffb578f3bddc381e2da8cd3 100644 (file)
@@ -576,7 +576,7 @@ xfs_attri_item_recover(
        struct xfs_trans_res            tres;
        struct xfs_attri_log_format     *attrp;
        struct xfs_attri_log_nameval    *nv = attrip->attri_nameval;
-       int                             error, ret = 0;
+       int                             error;
        int                             total;
        int                             local;
        struct xfs_attrd_log_item       *done_item = NULL;
@@ -655,29 +655,32 @@ xfs_attri_item_recover(
        xfs_ilock(ip, XFS_ILOCK_EXCL);
        xfs_trans_ijoin(tp, ip, 0);
 
-       ret = xfs_xattri_finish_update(attr, done_item);
-       if (ret == -EAGAIN) {
-               /* There's more work to do, so add it to this transaction */
+       error = xfs_xattri_finish_update(attr, done_item);
+       if (error == -EAGAIN) {
+               /*
+                * There's more work to do, so add the intent item to this
+                * transaction so that we can continue it later.
+                */
                xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_ATTR, &attr->xattri_list);
-       } else
-               error = ret;
+               error = xfs_defer_ops_capture_and_commit(tp, capture_list);
+               if (error)
+                       goto out_unlock;
 
+               xfs_iunlock(ip, XFS_ILOCK_EXCL);
+               xfs_irele(ip);
+               return 0;
+       }
        if (error) {
                xfs_trans_cancel(tp);
                goto out_unlock;
        }
 
        error = xfs_defer_ops_capture_and_commit(tp, capture_list);
-
 out_unlock:
-       if (attr->xattri_leaf_bp)
-               xfs_buf_relse(attr->xattri_leaf_bp);
-
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        xfs_irele(ip);
 out:
-       if (ret != -EAGAIN)
-               xfs_attr_free_item(attr);
+       xfs_attr_free_item(attr);
        return error;
 }
 
index 52be58372c632b1b7b63cc8336047cb0f58a53bd..85e1a26c92e875a573d01853e301d7c207d538ce 100644 (file)
@@ -686,6 +686,8 @@ xfs_can_free_eofblocks(
         * forever.
         */
        end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip));
+       if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1)
+               end_fsb = roundup_64(end_fsb, mp->m_sb.sb_rextsize);
        last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
        if (last_fsb <= end_fsb)
                return false;
index 5269354b1b69d432aa1f7cfb7852da3055dbc3b8..2609825d53eed6f67baa8e3b140b8c5b4a8f3d91 100644 (file)
@@ -440,7 +440,7 @@ xfs_inodegc_queue_all(
        for_each_online_cpu(cpu) {
                gc = per_cpu_ptr(mp->m_inodegc, cpu);
                if (!llist_empty(&gc->list))
-                       queue_work_on(cpu, mp->m_inodegc_wq, &gc->work);
+                       mod_delayed_work_on(cpu, mp->m_inodegc_wq, &gc->work, 0);
        }
 }
 
@@ -1841,8 +1841,8 @@ void
 xfs_inodegc_worker(
        struct work_struct      *work)
 {
-       struct xfs_inodegc      *gc = container_of(work, struct xfs_inodegc,
-                                                       work);
+       struct xfs_inodegc      *gc = container_of(to_delayed_work(work),
+                                               struct xfs_inodegc, work);
        struct llist_node       *node = llist_del_all(&gc->list);
        struct xfs_inode        *ip, *n;
 
@@ -1862,19 +1862,29 @@ xfs_inodegc_worker(
 }
 
 /*
- * Force all currently queued inode inactivation work to run immediately and
- * wait for the work to finish.
+ * Expedite all pending inodegc work to run immediately. This does not wait for
+ * completion of the work.
  */
 void
-xfs_inodegc_flush(
+xfs_inodegc_push(
        struct xfs_mount        *mp)
 {
        if (!xfs_is_inodegc_enabled(mp))
                return;
+       trace_xfs_inodegc_push(mp, __return_address);
+       xfs_inodegc_queue_all(mp);
+}
 
+/*
+ * Force all currently queued inode inactivation work to run immediately and
+ * wait for the work to finish.
+ */
+void
+xfs_inodegc_flush(
+       struct xfs_mount        *mp)
+{
+       xfs_inodegc_push(mp);
        trace_xfs_inodegc_flush(mp, __return_address);
-
-       xfs_inodegc_queue_all(mp);
        flush_workqueue(mp->m_inodegc_wq);
 }
 
@@ -2014,6 +2024,7 @@ xfs_inodegc_queue(
        struct xfs_inodegc      *gc;
        int                     items;
        unsigned int            shrinker_hits;
+       unsigned long           queue_delay = 1;
 
        trace_xfs_inode_set_need_inactive(ip);
        spin_lock(&ip->i_flags_lock);
@@ -2025,19 +2036,26 @@ xfs_inodegc_queue(
        items = READ_ONCE(gc->items);
        WRITE_ONCE(gc->items, items + 1);
        shrinker_hits = READ_ONCE(gc->shrinker_hits);
-       put_cpu_ptr(gc);
 
-       if (!xfs_is_inodegc_enabled(mp))
+       /*
+        * We queue the work while holding the current CPU so that the work
+        * is scheduled to run on this CPU.
+        */
+       if (!xfs_is_inodegc_enabled(mp)) {
+               put_cpu_ptr(gc);
                return;
-
-       if (xfs_inodegc_want_queue_work(ip, items)) {
-               trace_xfs_inodegc_queue(mp, __return_address);
-               queue_work(mp->m_inodegc_wq, &gc->work);
        }
 
+       if (xfs_inodegc_want_queue_work(ip, items))
+               queue_delay = 0;
+
+       trace_xfs_inodegc_queue(mp, __return_address);
+       mod_delayed_work(mp->m_inodegc_wq, &gc->work, queue_delay);
+       put_cpu_ptr(gc);
+
        if (xfs_inodegc_want_flush_work(ip, items, shrinker_hits)) {
                trace_xfs_inodegc_throttle(mp, __return_address);
-               flush_work(&gc->work);
+               flush_delayed_work(&gc->work);
        }
 }
 
@@ -2054,7 +2072,7 @@ xfs_inodegc_cpu_dead(
        unsigned int            count = 0;
 
        dead_gc = per_cpu_ptr(mp->m_inodegc, dead_cpu);
-       cancel_work_sync(&dead_gc->work);
+       cancel_delayed_work_sync(&dead_gc->work);
 
        if (llist_empty(&dead_gc->list))
                return;
@@ -2073,12 +2091,12 @@ xfs_inodegc_cpu_dead(
        llist_add_batch(first, last, &gc->list);
        count += READ_ONCE(gc->items);
        WRITE_ONCE(gc->items, count);
-       put_cpu_ptr(gc);
 
        if (xfs_is_inodegc_enabled(mp)) {
                trace_xfs_inodegc_queue(mp, __return_address);
-               queue_work(mp->m_inodegc_wq, &gc->work);
+               mod_delayed_work(mp->m_inodegc_wq, &gc->work, 0);
        }
+       put_cpu_ptr(gc);
 }
 
 /*
@@ -2173,7 +2191,7 @@ xfs_inodegc_shrinker_scan(
                        unsigned int    h = READ_ONCE(gc->shrinker_hits);
 
                        WRITE_ONCE(gc->shrinker_hits, h + 1);
-                       queue_work_on(cpu, mp->m_inodegc_wq, &gc->work);
+                       mod_delayed_work_on(cpu, mp->m_inodegc_wq, &gc->work, 0);
                        no_items = false;
                }
        }
index 2e4cfddf8b8ed8faeb49bd5c54e0c501fb2b4b8c..6cd180721659b28f9aa122f8f8bc03296ac92b3e 100644 (file)
@@ -76,6 +76,7 @@ void xfs_blockgc_stop(struct xfs_mount *mp);
 void xfs_blockgc_start(struct xfs_mount *mp);
 
 void xfs_inodegc_worker(struct work_struct *work);
+void xfs_inodegc_push(struct xfs_mount *mp);
 void xfs_inodegc_flush(struct xfs_mount *mp);
 void xfs_inodegc_stop(struct xfs_mount *mp);
 void xfs_inodegc_start(struct xfs_mount *mp);
index 52d6f2c7d58b3722e6e28ecb15b9165ea56dda02..3e1c62ffa4f76ef35513464b55fd23ffa07607c2 100644 (file)
@@ -131,6 +131,26 @@ xfs_ilock_attr_map_shared(
        return lock_mode;
 }
 
+/*
+ * You can't set both SHARED and EXCL for the same lock,
+ * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_MMAPLOCK_SHARED,
+ * XFS_MMAPLOCK_EXCL, XFS_ILOCK_SHARED, XFS_ILOCK_EXCL are valid values
+ * to set in lock_flags.
+ */
+static inline void
+xfs_lock_flags_assert(
+       uint            lock_flags)
+{
+       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
+               (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
+       ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) !=
+               (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL));
+       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
+               (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
+       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_SUBCLASS_MASK)) == 0);
+       ASSERT(lock_flags != 0);
+}
+
 /*
  * In addition to i_rwsem in the VFS inode, the xfs inode contains 2
  * multi-reader locks: invalidate_lock and the i_lock.  This routine allows
@@ -168,18 +188,7 @@ xfs_ilock(
 {
        trace_xfs_ilock(ip, lock_flags, _RET_IP_);
 
-       /*
-        * You can't set both SHARED and EXCL for the same lock,
-        * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
-        * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
-        */
-       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
-              (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) !=
-              (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
-              (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_SUBCLASS_MASK)) == 0);
+       xfs_lock_flags_assert(lock_flags);
 
        if (lock_flags & XFS_IOLOCK_EXCL) {
                down_write_nested(&VFS_I(ip)->i_rwsem,
@@ -222,18 +231,7 @@ xfs_ilock_nowait(
 {
        trace_xfs_ilock_nowait(ip, lock_flags, _RET_IP_);
 
-       /*
-        * You can't set both SHARED and EXCL for the same lock,
-        * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
-        * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
-        */
-       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
-              (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) !=
-              (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
-              (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_SUBCLASS_MASK)) == 0);
+       xfs_lock_flags_assert(lock_flags);
 
        if (lock_flags & XFS_IOLOCK_EXCL) {
                if (!down_write_trylock(&VFS_I(ip)->i_rwsem))
@@ -291,19 +289,7 @@ xfs_iunlock(
        xfs_inode_t             *ip,
        uint                    lock_flags)
 {
-       /*
-        * You can't set both SHARED and EXCL for the same lock,
-        * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
-        * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
-        */
-       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
-              (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) !=
-              (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
-              (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_SUBCLASS_MASK)) == 0);
-       ASSERT(lock_flags != 0);
+       xfs_lock_flags_assert(lock_flags);
 
        if (lock_flags & XFS_IOLOCK_EXCL)
                up_write(&VFS_I(ip)->i_rwsem);
@@ -379,8 +365,8 @@ xfs_isilocked(
        }
 
        if (lock_flags & (XFS_MMAPLOCK_EXCL|XFS_MMAPLOCK_SHARED)) {
-               return __xfs_rwsem_islocked(&VFS_I(ip)->i_rwsem,
-                               (lock_flags & XFS_IOLOCK_SHARED));
+               return __xfs_rwsem_islocked(&VFS_I(ip)->i_mapping->invalidate_lock,
+                               (lock_flags & XFS_MMAPLOCK_SHARED));
        }
 
        if (lock_flags & (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED)) {
index 1e972f884a812c831384ba05855ae99ef002b559..ae904b21e9cc7aae7fd742d67f61bb594a2889ea 100644 (file)
@@ -2092,8 +2092,6 @@ xlog_dealloc_log(
        xlog_in_core_t  *iclog, *next_iclog;
        int             i;
 
-       xlog_cil_destroy(log);
-
        /*
         * Cycle all the iclogbuf locks to make sure all log IO completion
         * is done before we tear down these buffers.
@@ -2105,6 +2103,13 @@ xlog_dealloc_log(
                iclog = iclog->ic_next;
        }
 
+       /*
+        * Destroy the CIL after waiting for iclog IO completion because an
+        * iclog EIO error will try to shut down the log, which accesses the
+        * CIL to wake up the waiters.
+        */
+       xlog_cil_destroy(log);
+
        iclog = log->l_iclog;
        for (i = 0; i < log->l_iclog_bufs; i++) {
                next_iclog = iclog->ic_next;
index ba5d42abf66e003fa7573cd928a0a5f4b9b82213..d2eaebd85abfa0c2424d50a2ab62bf6d15441ec9 100644 (file)
@@ -61,7 +61,7 @@ struct xfs_error_cfg {
  */
 struct xfs_inodegc {
        struct llist_head       list;
-       struct work_struct      work;
+       struct delayed_work     work;
 
        /* approximate count of inodes in the list */
        unsigned int            items;
index 74ac9ca9e119d7b2fb983096bd6e8e1ebd0eb5e3..392cb39cc10c8395acbef5097b79057930d4dbc7 100644 (file)
@@ -454,9 +454,12 @@ xfs_qm_scall_getquota(
        struct xfs_dquot        *dqp;
        int                     error;
 
-       /* Flush inodegc work at the start of a quota reporting scan. */
+       /*
+        * Expedite pending inodegc work at the start of a quota reporting
+        * scan but don't block waiting for it to complete.
+        */
        if (id == 0)
-               xfs_inodegc_flush(mp);
+               xfs_inodegc_push(mp);
 
        /*
         * Try to get the dquot. We don't want it allocated on disk, so don't
@@ -498,7 +501,7 @@ xfs_qm_scall_getquota_next(
 
        /* Flush inodegc work at the start of a quota reporting scan. */
        if (*id == 0)
-               xfs_inodegc_flush(mp);
+               xfs_inodegc_push(mp);
 
        error = xfs_qm_dqget_next(mp, *id, type, &dqp);
        if (error)
index ed18160e6181cf4a5c1373f9e1ccaa65ee93d07e..aa977c7ea370b0fba0140bf9d9be8fc129aa9bb0 100644 (file)
@@ -797,8 +797,11 @@ xfs_fs_statfs(
        xfs_extlen_t            lsize;
        int64_t                 ffree;
 
-       /* Wait for whatever inactivations are in progress. */
-       xfs_inodegc_flush(mp);
+       /*
+        * Expedite background inodegc but don't wait. We do not want to block
+        * here waiting hours for a billion extent file to be truncated.
+        */
+       xfs_inodegc_push(mp);
 
        statp->f_type = XFS_SUPER_MAGIC;
        statp->f_namelen = MAXNAMELEN - 1;
@@ -1074,7 +1077,7 @@ xfs_inodegc_init_percpu(
                gc = per_cpu_ptr(mp->m_inodegc, cpu);
                init_llist_head(&gc->list);
   &