Merge tag 'mlx5-fixes-2019-06-07' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorDavid S. Miller <davem@davemloft.net>
Mon, 10 Jun 2019 02:45:54 +0000 (19:45 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 10 Jun 2019 02:45:54 +0000 (19:45 -0700)
Saeed Mahameed says:

====================
Mellanox, mlx5 fixes 2019-06-07

This series introduces some fixes to mlx5 driver.

Please pull and let me know if there is any problem.

For -stable v4.17
  ('net/mlx5: Avoid reloading already removed devices')

For -stable v5.0
  ('net/mlx5e: Avoid detaching non-existing netdev under switchdev mode')

For -stable v5.1
  ('net/mlx5e: Fix source port matching in fdb peer flow rule')
  ('net/mlx5e: Support tagged tunnel over bond')
  ('net/mlx5e: Add ndo_set_feature for uplink representor')
  ('net/mlx5: Update pci error handler entries and command translation')
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
212 files changed:
Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt
Documentation/filesystems/overlayfs.txt
Documentation/networking/af_xdp.rst
MAINTAINERS
arch/arc/boot/dts/hsdk.dts
arch/arc/configs/hsdk_defconfig
arch/arc/include/asm/cmpxchg.h
arch/arc/mm/fault.c
arch/arc/mm/tlb.c
arch/arm64/Makefile
arch/arm64/include/asm/arch_timer.h
arch/arm64/include/asm/smp.h
arch/arm64/include/asm/smp_plat.h
arch/arm64/include/asm/thread_info.h
arch/arm64/kernel/cpufeature.c
arch/nds32/include/asm/bitfield.h
arch/nds32/include/asm/fpu.h
arch/nds32/include/asm/fpuemu.h
arch/nds32/include/asm/syscalls.h
arch/nds32/include/uapi/asm/fp_udfiex_crtl.h [new file with mode: 0644]
arch/nds32/include/uapi/asm/sigcontext.h
arch/nds32/include/uapi/asm/udftrap.h [deleted file]
arch/nds32/include/uapi/asm/unistd.h
arch/nds32/kernel/fpu.c
arch/nds32/kernel/sys_nds32.c
arch/nds32/math-emu/Makefile
arch/nds32/math-emu/fd2si.c [new file with mode: 0644]
arch/nds32/math-emu/fd2siz.c [new file with mode: 0644]
arch/nds32/math-emu/fd2ui.c [new file with mode: 0644]
arch/nds32/math-emu/fd2uiz.c [new file with mode: 0644]
arch/nds32/math-emu/fpuemu.c
arch/nds32/math-emu/fs2si.c [new file with mode: 0644]
arch/nds32/math-emu/fs2siz.c [new file with mode: 0644]
arch/nds32/math-emu/fs2ui.c [new file with mode: 0644]
arch/nds32/math-emu/fs2uiz.c [new file with mode: 0644]
arch/nds32/math-emu/fsi2d.c [new file with mode: 0644]
arch/nds32/math-emu/fsi2s.c [new file with mode: 0644]
arch/nds32/math-emu/fui2d.c [new file with mode: 0644]
arch/nds32/math-emu/fui2s.c [new file with mode: 0644]
arch/parisc/Kconfig
arch/parisc/configs/712_defconfig
arch/parisc/configs/a500_defconfig
arch/parisc/configs/b180_defconfig
arch/parisc/configs/c3000_defconfig
arch/parisc/configs/c8000_defconfig
arch/parisc/configs/default_defconfig
arch/parisc/configs/generic-32bit_defconfig
arch/parisc/include/asm/special_insns.h
arch/parisc/kernel/alternative.c
arch/parisc/kernel/vmlinux.lds.S
arch/parisc/math-emu/cnv_float.h
arch/riscv/net/bpf_jit_comp.c
arch/sparc/kernel/mdesc.c
arch/sparc/kernel/perf_event.c
arch/sparc/mm/ultra.S
crypto/hmac.c
crypto/jitterentropy-kcapi.c
drivers/infiniband/core/device.c
drivers/infiniband/core/rdma_core.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_std_types_cq.c
drivers/infiniband/core/uverbs_std_types_mr.c
drivers/infiniband/hw/efa/efa_verbs.c
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/user_exp_rcv.c
drivers/infiniband/hw/hfi1/verbs.c
drivers/infiniband/hw/hns/hns_roce_hw_v1.c
drivers/infiniband/hw/mlx5/cmd.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/qib/qib_verbs.c
drivers/infiniband/sw/rdmavt/mr.c
drivers/infiniband/sw/rdmavt/qp.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/net/can/flexcan.c
drivers/net/can/m_can/m_can.c
drivers/net/can/spi/Kconfig
drivers/net/can/spi/mcp251x.c
drivers/net/can/usb/Kconfig
drivers/net/can/xilinx_can.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/ethernet/8390/Kconfig
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/ti/cpsw_ethtool.c
drivers/net/ipvlan/ipvlan_main.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/asix.c [deleted file]
drivers/net/phy/ax88796b.c [new file with mode: 0644]
drivers/net/phy/phylink.c
drivers/net/phy/sfp.c
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/fw/dbg.h
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
drivers/net/wireless/intel/iwlwifi/iwl-prph.h
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
drivers/net/wireless/intel/iwlwifi/mvm/utils.c
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/marvell/mwifiex/ie.c
drivers/net/wireless/marvell/mwifiex/scan.c
drivers/net/wireless/realtek/rtw88/fw.c
drivers/net/wireless/realtek/rtw88/main.c
drivers/net/wireless/realtek/rtw88/phy.c
drivers/net/wireless/rsi/rsi_91x_sdio.c
drivers/parisc/ccio-dma.c
drivers/parisc/sba_iommu.c
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/vhost/net.c
drivers/vhost/scsi.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/vhost/vsock.c
drivers/virtio/Kconfig
fs/adfs/adfs.h
fs/adfs/dir.c
fs/adfs/dir_f.c
fs/adfs/dir_fplus.c
fs/fuse/file.c
fs/gfs2/glock.c
fs/gfs2/incore.h
fs/gfs2/log.c
fs/gfs2/lops.c
fs/gfs2/main.c
fs/gfs2/super.c
fs/nfs/nfs4proc.c
fs/overlayfs/file.c
fs/overlayfs/inode.c
fs/overlayfs/namei.c
fs/overlayfs/overlayfs.h
fs/overlayfs/ovl_entry.h
fs/overlayfs/super.c
fs/overlayfs/util.c
fs/pstore/platform.c
fs/pstore/ram.c
fs/xfs/scrub/ialloc.c
fs/xfs/xfs_log.c
include/linux/bpf-cgroup.h
include/linux/dsa/sja1105.h
include/linux/rcupdate.h
include/linux/skmsg.h
include/math-emu/op-2.h
include/math-emu/op-common.h
include/net/ip6_fib.h
include/net/tls.h
include/rdma/ib_verbs.h
include/uapi/linux/bpf.h
include/uapi/linux/fuse.h
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/signal.c
net/can/af_can.c
net/core/dev.c
net/core/ethtool.c
net/core/fib_rules.c
net/core/filter.c
net/core/pktgen.c
net/core/skbuff.c
net/dsa/tag_sja1105.c
net/ipv4/fib_semantics.c
net/ipv4/route.c
net/ipv4/udp.c
net/ipv6/ip6_flowlabel.c
net/ipv6/raw.c
net/ipv6/udp.c
net/mpls/mpls_iptunnel.c
net/packet/af_packet.c
net/rds/ib.c
net/rds/ib_rdma.c
net/rds/ib_recv.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sunrpc/clnt.c
net/sunrpc/xprtrdma/verbs.c
net/tls/tls_device.c
samples/bpf/bpf_load.c
samples/bpf/task_fd_query_user.c
samples/pidfd/pidfd-metadata.c
tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
tools/bpf/bpftool/Documentation/bpftool-prog.rst
tools/bpf/bpftool/bash-completion/bpftool
tools/bpf/bpftool/cgroup.c
tools/bpf/bpftool/map.c
tools/bpf/bpftool/prog.c
tools/include/uapi/linux/bpf.h
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf_internal.h
tools/lib/bpf/libbpf_probes.c
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/prog_tests/flow_dissector.c
tools/testing/selftests/bpf/test_section_names.c
tools/testing/selftests/bpf/test_sock_addr.c
tools/testing/selftests/bpf/verifier/subreg.c [new file with mode: 0644]
tools/testing/selftests/cgroup/test_core.c
tools/testing/selftests/cgroup/test_memcontrol.c
tools/testing/selftests/net/forwarding/router_broadcast.sh
tools/testing/selftests/pidfd/pidfd_test.c
tools/testing/selftests/vm/Makefile
tools/testing/selftests/vm/userfaultfd.c
tools/virtio/linux/kernel.h

index 188c8bd..5a0111d 100644 (file)
@@ -4,6 +4,7 @@ Required properties:
  - compatible: Should be one of the following:
    - "microchip,mcp2510" for MCP2510.
    - "microchip,mcp2515" for MCP2515.
+   - "microchip,mcp25625" for MCP25625.
  - reg: SPI chip select.
  - clocks: The clock feeding the CAN controller.
  - interrupts: Should contain IRQ line for the CAN controller.
index eef7d9d..1da2f16 100644 (file)
@@ -336,8 +336,20 @@ the copied layers will fail the verification of the lower root file handle.
 Non-standard behavior
 ---------------------
 
-Overlayfs can now act as a POSIX compliant filesystem with the following
-features turned on:
+Current version of overlayfs can act as a mostly POSIX compliant
+filesystem.
+
+This is the list of cases that overlayfs doesn't currently handle:
+
+a) POSIX mandates updating st_atime for reads.  This is currently not
+done in the case when the file resides on a lower layer.
+
+b) If a file residing on a lower layer is opened for read-only and then
+memory mapped with MAP_SHARED, then subsequent changes to the file are not
+reflected in the memory mapping.
+
+The following options allow overlayfs to act more like a standards
+compliant filesystem:
 
 1) "redirect_dir"
 
index e14d7d4..50bccbf 100644 (file)
@@ -316,16 +316,16 @@ A: When a netdev of a physical NIC is initialized, Linux usually
    all the traffic, you can force the netdev to only have 1 queue, queue
    id 0, and then bind to queue 0. You can use ethtool to do this::
 
-   sudo ethtool -L <interface> combined 1
+     sudo ethtool -L <interface> combined 1
 
    If you want to only see part of the traffic, you can program the
    NIC through ethtool to filter out your traffic to a single queue id
    that you can bind your XDP socket to. Here is one example in which
    UDP traffic to and from port 4242 are sent to queue 2::
 
-   sudo ethtool -N <interface> rx-flow-hash udp4 fn
-   sudo ethtool -N <interface> flow-type udp4 src-port 4242 dst-port \
-   4242 action 2
+     sudo ethtool -N <interface> rx-flow-hash udp4 fn
+     sudo ethtool -N <interface> flow-type udp4 src-port 4242 dst-port \
+     4242 action 2
 
    A number of other ways are possible all up to the capabilitites of
    the NIC you have.
index a695477..36a8461 100644 (file)
@@ -17312,7 +17312,7 @@ F:      Documentation/ABI/stable/sysfs-hypervisor-xen
 F:     Documentation/ABI/testing/sysfs-hypervisor-xen
 
 XEN NETWORK BACKEND DRIVER
-M:     Wei Liu <wei.liu2@citrix.com>
+M:     Wei Liu <wei.liu@kernel.org>
 M:     Paul Durrant <paul.durrant@citrix.com>
 L:     xen-devel@lists.xenproject.org (moderated for non-subscribers)
 L:     netdev@vger.kernel.org
index 7425bb0..acfbed4 100644 (file)
@@ -11,7 +11,6 @@
  */
 /dts-v1/;
 
-#include <dt-bindings/net/ti-dp83867.h>
 #include <dt-bindings/reset/snps,hsdk-reset.h>
 
 / {
                        #clock-cells = <0>;
                };
 
+               gpu_core_clk: gpu-core-clk {
+                       compatible = "fixed-clock";
+                       clock-frequency = <400000000>;
+                       #clock-cells = <0>;
+               };
+
+               gpu_dma_clk: gpu-dma-clk {
+                       compatible = "fixed-clock";
+                       clock-frequency = <400000000>;
+                       #clock-cells = <0>;
+               };
+
+               gpu_cfg_clk: gpu-cfg-clk {
+                       compatible = "fixed-clock";
+                       clock-frequency = <200000000>;
+                       #clock-cells = <0>;
+               };
+
                dmac_core_clk: dmac-core-clk {
                        compatible = "fixed-clock";
                        clock-frequency = <400000000>;
                        interrupt-names = "macirq";
                        phy-mode = "rgmii";
                        snps,pbl = <32>;
+                       snps,multicast-filter-bins = <256>;
                        clocks = <&gmacclk>;
                        clock-names = "stmmaceth";
                        phy-handle = <&phy0>;
                        mac-address = [00 00 00 00 00 00]; /* Filled in by U-Boot */
                        dma-coherent;
 
+                       tx-fifo-depth = <4096>;
+                       rx-fifo-depth = <4096>;
+
                        mdio {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "snps,dwmac-mdio";
                                phy0: ethernet-phy@0 {
                                        reg = <0>;
-                                       ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
-                                       ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
-                                       ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
                                };
                        };
                };
                        dma-coherent;
                };
 
+               creg_gpio: gpio@14b0 {
+                       compatible = "snps,creg-gpio-hsdk";
+                       reg = <0x14b0 0x4>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       ngpios = <2>;
+               };
+
                gpio: gpio@3000 {
                        compatible = "snps,dw-apb-gpio";
                        reg = <0x3000 0x20>;
                        };
                };
 
+               gpu_3d: gpu@90000 {
+                       compatible = "vivante,gc";
+                       reg = <0x90000 0x4000>;
+                       clocks = <&gpu_dma_clk>,
+                                <&gpu_cfg_clk>,
+                                <&gpu_core_clk>,
+                                <&gpu_core_clk>;
+                       clock-names = "bus", "reg", "core", "shader";
+                       interrupts = <28>;
+               };
+
                dmac: dmac@80000 {
                        compatible = "snps,axi-dma-1.01a";
                        reg = <0x80000 0x400>;
index 0e5fd29..c8fb5d6 100644 (file)
@@ -49,10 +49,12 @@ CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_DWAPB=y
+CONFIG_GPIO_SNPS_CREG=y
 # CONFIG_HWMON is not set
 CONFIG_DRM=y
 # CONFIG_DRM_FBDEV_EMULATION is not set
 CONFIG_DRM_UDL=y
+CONFIG_DRM_ETNAVIV=y
 CONFIG_FB=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_USB_EHCI_HCD=y
@@ -64,7 +66,6 @@ CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_DW=y
-# CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT3_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
index d819de1..3ea4112 100644 (file)
@@ -92,8 +92,11 @@ __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
 
 #endif /* CONFIG_ARC_HAS_LLSC */
 
-#define cmpxchg(ptr, o, n) ((typeof(*(ptr)))__cmpxchg((ptr), \
-                               (unsigned long)(o), (unsigned long)(n)))
+#define cmpxchg(ptr, o, n) ({                          \
+       (typeof(*(ptr)))__cmpxchg((ptr),                \
+                                 (unsigned long)(o),   \
+                                 (unsigned long)(n));  \
+})
 
 /*
  * atomic_cmpxchg is same as cmpxchg
@@ -198,8 +201,11 @@ static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
        return __xchg_bad_pointer();
 }
 
-#define xchg(ptr, with) ((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), \
-                                                sizeof(*(ptr))))
+#define xchg(ptr, with) ({                             \
+       (typeof(*(ptr)))__xchg((unsigned long)(with),   \
+                              (ptr),                   \
+                              sizeof(*(ptr)));         \
+})
 
 #endif /* CONFIG_ARC_PLAT_EZNPS */
 
index 8df1638..6836095 100644 (file)
@@ -66,7 +66,7 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
        struct vm_area_struct *vma = NULL;
        struct task_struct *tsk = current;
        struct mm_struct *mm = tsk->mm;
-       int si_code = 0;
+       int si_code = SEGV_MAPERR;
        int ret;
        vm_fault_t fault;
        int write = regs->ecr_cause & ECR_C_PROTV_STORE;  /* ST/EX */
@@ -81,16 +81,14 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
         * only copy the information from the master page table,
         * nothing more.
         */
-       if (address >= VMALLOC_START) {
+       if (address >= VMALLOC_START && !user_mode(regs)) {
                ret = handle_kernel_vaddr_fault(address);
                if (unlikely(ret))
-                       goto bad_area_nosemaphore;
+                       goto no_context;
                else
                        return;
        }
 
-       si_code = SEGV_MAPERR;
-
        /*
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
@@ -198,7 +196,6 @@ good_area:
 bad_area:
        up_read(&mm->mmap_sem);
 
-bad_area_nosemaphore:
        /* User mode accesses just cause a SIGSEGV */
        if (user_mode(regs)) {
                tsk->thread.fault_address = address;
index 4097764..fa18c00 100644 (file)
@@ -911,9 +911,11 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
                          struct pt_regs *regs)
 {
        struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu;
-       unsigned int pd0[mmu->ways];
        unsigned long flags;
-       int set;
+       int set, n_ways = mmu->ways;
+
+       n_ways = min(n_ways, 4);
+       BUG_ON(mmu->ways > 4);
 
        local_irq_save(flags);
 
@@ -921,9 +923,10 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
        for (set = 0; set < mmu->sets; set++) {
 
                int is_valid, way;
+               unsigned int pd0[4];
 
                /* read out all the ways of current set */
-               for (way = 0, is_valid = 0; way < mmu->ways; way++) {
+               for (way = 0, is_valid = 0; way < n_ways; way++) {
                        write_aux_reg(ARC_REG_TLBINDEX,
                                          SET_WAY_TO_IDX(mmu, set, way));
                        write_aux_reg(ARC_REG_TLBCOMMAND, TLBRead);
@@ -937,14 +940,14 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
                        continue;
 
                /* Scan the set for duplicate ways: needs a nested loop */
-               for (way = 0; way < mmu->ways - 1; way++) {
+               for (way = 0; way < n_ways - 1; way++) {
 
                        int n;
 
                        if (!pd0[way])
                                continue;
 
-                       for (n = way + 1; n < mmu->ways; n++) {
+                       for (n = way + 1; n < n_ways; n++) {
                                if (pd0[way] != pd0[n])
                                        continue;
 
index b025304..8fbd583 100644 (file)
@@ -51,6 +51,7 @@ endif
 
 KBUILD_CFLAGS  += -mgeneral-regs-only $(lseinstr) $(brokengasinst)
 KBUILD_CFLAGS  += -fno-asynchronous-unwind-tables
+KBUILD_CFLAGS  += -Wno-psabi
 KBUILD_AFLAGS  += $(lseinstr) $(brokengasinst)
 
 KBUILD_CFLAGS  += $(call cc-option,-mabi=lp64)
index b7bca1a..50b3ab7 100644 (file)
@@ -193,7 +193,7 @@ static inline void arch_timer_set_cntkctl(u32 cntkctl)
        : "=r" (tmp) : "r" (_val));                                     \
 } while (0)
 
-static inline u64 __arch_counter_get_cntpct_stable(void)
+static __always_inline u64 __arch_counter_get_cntpct_stable(void)
 {
        u64 cnt;
 
@@ -203,7 +203,7 @@ static inline u64 __arch_counter_get_cntpct_stable(void)
        return cnt;
 }
 
-static inline u64 __arch_counter_get_cntpct(void)
+static __always_inline u64 __arch_counter_get_cntpct(void)
 {
        u64 cnt;
 
@@ -213,7 +213,7 @@ static inline u64 __arch_counter_get_cntpct(void)
        return cnt;
 }
 
-static inline u64 __arch_counter_get_cntvct_stable(void)
+static __always_inline u64 __arch_counter_get_cntvct_stable(void)
 {
        u64 cnt;
 
@@ -223,7 +223,7 @@ static inline u64 __arch_counter_get_cntvct_stable(void)
        return cnt;
 }
 
-static inline u64 __arch_counter_get_cntvct(void)
+static __always_inline u64 __arch_counter_get_cntvct(void)
 {
        u64 cnt;
 
index 18553f3..eae2d6c 100644 (file)
@@ -53,6 +53,12 @@ DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
  */
 #define raw_smp_processor_id() (*raw_cpu_ptr(&cpu_number))
 
+/*
+ * Logical CPU mapping.
+ */
+extern u64 __cpu_logical_map[NR_CPUS];
+#define cpu_logical_map(cpu)    __cpu_logical_map[cpu]
+
 struct seq_file;
 
 /*
index af58dcd..7a49540 100644 (file)
@@ -36,11 +36,6 @@ static inline u32 mpidr_hash_size(void)
        return 1 << mpidr_hash.bits;
 }
 
-/*
- * Logical CPU mapping.
- */
-extern u64 __cpu_logical_map[NR_CPUS];
-#define cpu_logical_map(cpu)    __cpu_logical_map[cpu]
 /*
  * Retrieve logical cpu index corresponding to a given MPIDR.Aff*
  *  - mpidr: MPIDR.Aff* bits to be used for the look-up
index eb3ef73..f1d032b 100644 (file)
@@ -75,7 +75,7 @@ void arch_release_task_struct(struct task_struct *tsk);
  *  TIF_SYSCALL_TRACE  - syscall trace active
  *  TIF_SYSCALL_TRACEPOINT - syscall tracepoint for ftrace
  *  TIF_SYSCALL_AUDIT  - syscall auditing
- *  TIF_SECOMP         - syscall secure computing
+ *  TIF_SECCOMP                - syscall secure computing
  *  TIF_SIGPENDING     - signal pending
  *  TIF_NEED_RESCHED   - rescheduling necessary
  *  TIF_NOTIFY_RESUME  - callback before returning to user
index ca27e08..80babf4 100644 (file)
@@ -830,6 +830,7 @@ static u64 __read_sysreg_by_encoding(u32 sys_id)
 
        read_sysreg_case(SYS_ID_AA64PFR0_EL1);
        read_sysreg_case(SYS_ID_AA64PFR1_EL1);
+       read_sysreg_case(SYS_ID_AA64ZFR0_EL1);
        read_sysreg_case(SYS_ID_AA64DFR0_EL1);
        read_sysreg_case(SYS_ID_AA64DFR1_EL1);
        read_sysreg_case(SYS_ID_AA64MMFR0_EL1);
index e75212c..b02a58e 100644 (file)
 #define FPCSR_mskDNIT           ( 0x1  << FPCSR_offDNIT )
 #define FPCSR_mskRIT           ( 0x1  << FPCSR_offRIT )
 #define FPCSR_mskALL           (FPCSR_mskIVO | FPCSR_mskDBZ | FPCSR_mskOVF | FPCSR_mskUDF | FPCSR_mskIEX)
-#define FPCSR_mskALLE_NO_UDFE  (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskIEXE)
+#define FPCSR_mskALLE_NO_UDF_IEXE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE)
 #define FPCSR_mskALLE          (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskUDFE | FPCSR_mskIEXE)
 #define FPCSR_mskALLT           (FPCSR_mskIVOT | FPCSR_mskDBZT | FPCSR_mskOVFT | FPCSR_mskUDFT | FPCSR_mskIEXT |FPCSR_mskDNIT | FPCSR_mskRIT)
 
index 019f1bc..8294ed4 100644 (file)
@@ -36,7 +36,7 @@ extern int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu);
  * enabled by default and kerenl will re-execute it by fpu emulator
  * when getting underflow exception.
  */
-#define FPCSR_INIT  FPCSR_mskUDFE
+#define FPCSR_INIT  (FPCSR_mskUDFE | FPCSR_mskIEXE)
 #else
 #define FPCSR_INIT  0x0UL
 #endif
index c4bd0c7..63e7ef5 100644 (file)
@@ -13,6 +13,12 @@ void fsubs(void *ft, void *fa, void *fb);
 void fmuls(void *ft, void *fa, void *fb);
 void fdivs(void *ft, void *fa, void *fb);
 void fs2d(void *ft, void *fa);
+void fs2si(void *ft, void *fa);
+void fs2si_z(void *ft, void *fa);
+void fs2ui(void *ft, void *fa);
+void fs2ui_z(void *ft, void *fa);
+void fsi2s(void *ft, void *fa);
+void fui2s(void *ft, void *fa);
 void fsqrts(void *ft, void *fa);
 void fnegs(void *ft, void *fa);
 int fcmps(void *ft, void *fa, void *fb, int cop);
@@ -26,6 +32,12 @@ void fmuld(void *ft, void *fa, void *fb);
 void fdivd(void *ft, void *fa, void *fb);
 void fsqrtd(void *ft, void *fa);
 void fd2s(void *ft, void *fa);
+void fd2si(void *ft, void *fa);
+void fd2si_z(void *ft, void *fa);
+void fd2ui(void *ft, void *fa);
+void fd2ui_z(void *ft, void *fa);
+void fsi2d(void *ft, void *fa);
+void fui2d(void *ft, void *fa);
 void fnegd(void *ft, void *fa);
 int fcmpd(void *ft, void *fa, void *fb, int cop);
 
index f3b16f6..4e72160 100644 (file)
@@ -7,7 +7,7 @@
 asmlinkage long sys_cacheflush(unsigned long addr, unsigned long len, unsigned int op);
 asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset, loff_t len);
 asmlinkage long sys_rt_sigreturn_wrapper(void);
-asmlinkage long sys_udftrap(int option);
+asmlinkage long sys_fp_udfiex_crtl(int cmd, int act);
 
 #include <asm-generic/syscalls.h>
 
diff --git a/arch/nds32/include/uapi/asm/fp_udfiex_crtl.h b/arch/nds32/include/uapi/asm/fp_udfiex_crtl.h
new file mode 100644 (file)
index 0000000..d54a5d6
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2005-2019 Andes Technology Corporation */
+#ifndef        _FP_UDF_IEX_CRTL_H
+#define        _FP_UDF_IEX_CRTL_H
+
+/*
+ * The cmd list of sys_fp_udfiex_crtl()
+ */
+/* Disable UDF or IEX trap based on the content of parameter act */
+#define DISABLE_UDF_IEX_TRAP   0
+/* Enable UDF or IEX trap based on the content of parameter act */
+#define ENABLE_UDF_IEX_TRAP    1
+/* Get current status of UDF and IEX trap */
+#define GET_UDF_IEX_TRAP       2
+
+#endif /* _FP_UDF_IEX_CRTL_H */
index 628ff6b..dc89af7 100644 (file)
@@ -13,14 +13,24 @@ struct fpu_struct {
        unsigned long long fd_regs[32];
        unsigned long fpcsr;
        /*
-        * UDF_trap is used to recognize whether underflow trap is enabled
-        * or not. When UDF_trap == 1, this process will be traped and then
-        * get a SIGFPE signal when encountering an underflow exception.
-        * UDF_trap is only modified through setfputrap syscall. Therefore,
-        * UDF_trap needn't be saved or loaded to context in each context
-        * switch.
+        * When CONFIG_SUPPORT_DENORMAL_ARITHMETIC is defined, kernel prevents
+        * hardware from treating the denormalized output as an underflow case
+        * and rounding it to a normal number. Hence kernel enables the UDF and
+        * IEX trap in the fpcsr register to step in the calculation.
+        * However, the UDF and IEX trap enable bit in $fpcsr also lose
+        * their use.
+        *
+        * UDF_IEX_trap replaces the feature of UDF and IEX trap enable bit in
+        * $fpcsr to control the trap of underflow and inexact. The bit filed
+        * of UDF_IEX_trap is the same as $fpcsr, 10th bit is used to enable UDF
+        * exception trapping and 11th bit is used to enable IEX exception
+        * trapping.
+        *
+        * UDF_IEX_trap is only modified through fp_udfiex_crtl syscall.
+        * Therefore, UDF_IEX_trap needn't be saved and restored in each
+        * context switch.
         */
-       unsigned long UDF_trap;
+       unsigned long UDF_IEX_trap;
 };
 
 struct zol_struct {
diff --git a/arch/nds32/include/uapi/asm/udftrap.h b/arch/nds32/include/uapi/asm/udftrap.h
deleted file mode 100644 (file)
index 433f79d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (C) 2005-2018 Andes Technology Corporation */
-#ifndef        _ASM_SETFPUTRAP
-#define        _ASM_SETFPUTRAP
-
-/*
- * Options for setfputrap system call
- */
-#define        DISABLE_UDFTRAP 0       /* disable underflow exception trap */
-#define        ENABLE_UDFTRAP  1       /* enable undeflos exception trap */
-#define        GET_UDFTRAP     2       /* only get undeflos exception trap status */
-
-#endif /* _ASM_CACHECTL */
index c691735..a0b2f7b 100644 (file)
@@ -11,6 +11,6 @@
 
 /* Additional NDS32 specific syscalls. */
 #define __NR_cacheflush                (__NR_arch_specific_syscall)
-#define __NR_udftrap           (__NR_arch_specific_syscall + 1)
+#define __NR_fp_udfiex_crtl    (__NR_arch_specific_syscall + 1)
 __SYSCALL(__NR_cacheflush, sys_cacheflush)
-__SYSCALL(__NR_udftrap, sys_udftrap)
+__SYSCALL(__NR_fp_udfiex_crtl, sys_fp_udfiex_crtl)
index fddd40c..cf0b876 100644 (file)
@@ -14,7 +14,7 @@ const struct fpu_struct init_fpuregs = {
        .fd_regs = {[0 ... 31] = sNAN64},
        .fpcsr = FPCSR_INIT,
 #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
-       .UDF_trap = 0
+       .UDF_IEX_trap = 0
 #endif
 };
 
@@ -178,7 +178,7 @@ inline void do_fpu_context_switch(struct pt_regs *regs)
                /* First time FPU user.  */
                load_fpu(&init_fpuregs);
 #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
-               current->thread.fpu.UDF_trap = init_fpuregs.UDF_trap;
+               current->thread.fpu.UDF_IEX_trap = init_fpuregs.UDF_IEX_trap;
 #endif
                set_used_math();
        }
@@ -206,7 +206,7 @@ inline void handle_fpu_exception(struct pt_regs *regs)
        unsigned int fpcsr;
        int si_code = 0, si_signo = SIGFPE;
 #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
-       unsigned long redo_except = FPCSR_mskDNIT|FPCSR_mskUDFT;
+       unsigned long redo_except = FPCSR_mskDNIT|FPCSR_mskUDFT|FPCSR_mskIEXT;
 #else
        unsigned long redo_except = FPCSR_mskDNIT;
 #endif
@@ -215,21 +215,18 @@ inline void handle_fpu_exception(struct pt_regs *regs)
        fpcsr = current->thread.fpu.fpcsr;
 
        if (fpcsr & redo_except) {
-#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
-               if (fpcsr & FPCSR_mskUDFT)
-                       current->thread.fpu.fpcsr &= ~FPCSR_mskIEX;
-#endif
                si_signo = do_fpuemu(regs, &current->thread.fpu);
                fpcsr = current->thread.fpu.fpcsr;
-               if (!si_signo)
+               if (!si_signo) {
+                       current->thread.fpu.fpcsr &= ~(redo_except);
                        goto done;
+               }
        } else if (fpcsr & FPCSR_mskRIT) {
                if (!user_mode(regs))
                        do_exit(SIGILL);
                si_signo = SIGILL;
        }
 
-
        switch (si_signo) {
        case SIGFPE:
                fill_sigfpe_signo(fpcsr, &si_code);
index 0835277..cb2d1e2 100644 (file)
@@ -6,8 +6,8 @@
 
 #include <asm/cachectl.h>
 #include <asm/proc-fns.h>
-#include <asm/udftrap.h>
 #include <asm/fpu.h>
+#include <asm/fp_udfiex_crtl.h>
 
 SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
               unsigned long, prot, unsigned long, flags,
@@ -51,31 +51,33 @@ SYSCALL_DEFINE3(cacheflush, unsigned int, start, unsigned int, end, int, cache)
        return 0;
 }
 
-SYSCALL_DEFINE1(udftrap, int, option)
+SYSCALL_DEFINE2(fp_udfiex_crtl, unsigned int, cmd, unsigned int, act)
 {
 #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
-       int old_udftrap;
+       int old_udf_iex;
 
        if (!used_math()) {
                load_fpu(&init_fpuregs);
-               current->thread.fpu.UDF_trap = init_fpuregs.UDF_trap;
+               current->thread.fpu.UDF_IEX_trap = init_fpuregs.UDF_IEX_trap;
                set_used_math();
        }
 
-       old_udftrap = current->thread.fpu.UDF_trap;
-       switch (option) {
-       case DISABLE_UDFTRAP:
-               current->thread.fpu.UDF_trap = 0;
+       old_udf_iex = current->thread.fpu.UDF_IEX_trap;
+       act &= (FPCSR_mskUDFE | FPCSR_mskIEXE);
+
+       switch (cmd) {
+       case DISABLE_UDF_IEX_TRAP:
+               current->thread.fpu.UDF_IEX_trap &= ~act;
                break;
-       case ENABLE_UDFTRAP:
-               current->thread.fpu.UDF_trap = FPCSR_mskUDFE;
+       case ENABLE_UDF_IEX_TRAP:
+               current->thread.fpu.UDF_IEX_trap |= act;
                break;
-       case GET_UDFTRAP:
+       case GET_UDF_IEX_TRAP:
                break;
        default:
                return -EINVAL;
        }
-       return old_udftrap;
+       return old_udf_iex;
 #else
        return -ENOTSUPP;
 #endif
index 14fa01f..3bed7e5 100644 (file)
@@ -5,4 +5,6 @@
 
 obj-y  := fpuemu.o \
           fdivd.o fmuld.o fsubd.o faddd.o fs2d.o fsqrtd.o fcmpd.o fnegs.o \
-          fdivs.o fmuls.o fsubs.o fadds.o fd2s.o fsqrts.o fcmps.o fnegd.o
+          fd2si.o fd2ui.o fd2siz.o fd2uiz.o fsi2d.o fui2d.o \
+          fdivs.o fmuls.o fsubs.o fadds.o fd2s.o fsqrts.o fcmps.o fnegd.o \
+          fs2si.o fs2ui.o fs2siz.o fs2uiz.o fsi2s.o fui2s.o
diff --git a/arch/nds32/math-emu/fd2si.c b/arch/nds32/math-emu/fd2si.c
new file mode 100644 (file)
index 0000000..fae3e16
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2019 Andes Technology Corporation
+#include <linux/uaccess.h>
+
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+
+void fd2si(void *ft, void *fa)
+{
+       int r;
+
+       FP_DECL_D(A);
+       FP_DECL_EX;
+
+       FP_UNPACK_DP(A, fa);
+
+       if (A_c == FP_CLS_INF) {
+               *(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else if (A_c == FP_CLS_NAN) {
+               *(int *)ft = 0xffffffff;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else {
+               FP_TO_INT_ROUND_D(r, A, 32, 1);
+               __FPU_FPCSR |= FP_CUR_EXCEPTIONS;
+               *(int *)ft = r;
+       }
+
+}
diff --git a/arch/nds32/math-emu/fd2siz.c b/arch/nds32/math-emu/fd2siz.c
new file mode 100644 (file)
index 0000000..92fe677
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2019 Andes Technology Corporation
+#include <linux/uaccess.h>
+
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+
+void fd2si_z(void *ft, void *fa)
+{
+       int r;
+
+       FP_DECL_D(A);
+       FP_DECL_EX;
+
+       FP_UNPACK_DP(A, fa);
+
+       if (A_c == FP_CLS_INF) {
+               *(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else if (A_c == FP_CLS_NAN) {
+               *(int *)ft = 0xffffffff;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else {
+               FP_TO_INT_D(r, A, 32, 1);
+               __FPU_FPCSR |= FP_CUR_EXCEPTIONS;
+               *(int *)ft = r;
+       }
+
+}
diff --git a/arch/nds32/math-emu/fd2ui.c b/arch/nds32/math-emu/fd2ui.c
new file mode 100644 (file)
index 0000000..a0423b6
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2019 Andes Technology Corporation
+#include <linux/uaccess.h>
+
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+
+void fd2ui(void *ft, void *fa)
+{
+       unsigned int r;
+
+       FP_DECL_D(A);
+       FP_DECL_EX;
+
+       FP_UNPACK_DP(A, fa);
+
+       if (A_c == FP_CLS_INF) {
+               *(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else if (A_c == FP_CLS_NAN) {
+               *(unsigned int *)ft = 0xffffffff;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else {
+               FP_TO_INT_ROUND_D(r, A, 32, 0);
+               __FPU_FPCSR |= FP_CUR_EXCEPTIONS;
+               *(unsigned int *)ft = r;
+       }
+
+}
diff --git a/arch/nds32/math-emu/fd2uiz.c b/arch/nds32/math-emu/fd2uiz.c
new file mode 100644 (file)
index 0000000..8ae17cf
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2019 Andes Technology Corporation
+#include <linux/uaccess.h>
+
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+
+void fd2ui_z(void *ft, void *fa)
+{
+       unsigned int r;
+
+       FP_DECL_D(A);
+       FP_DECL_EX;
+
+       FP_UNPACK_DP(A, fa);
+
+       if (A_c == FP_CLS_INF) {
+               *(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else if (A_c == FP_CLS_NAN) {
+               *(unsigned int *)ft = 0xffffffff;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else {
+               FP_TO_INT_D(r, A, 32, 0);
+               __FPU_FPCSR |= FP_CUR_EXCEPTIONS;
+               *(unsigned int *)ft = r;
+       }
+
+}
index 75cf164..46558a1 100644 (file)
@@ -113,6 +113,30 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn)
                                        func.b = fs2d;
                                        ftype = S1D;
                                        break;
+                               case fs2si_op:
+                                       func.b = fs2si;
+                                       ftype = S1S;
+                                       break;
+                               case fs2si_z_op:
+                                       func.b = fs2si_z;
+                                       ftype = S1S;
+                                       break;
+                               case fs2ui_op:
+                                       func.b = fs2ui;
+                                       ftype = S1S;
+                                       break;
+                               case fs2ui_z_op:
+                                       func.b = fs2ui_z;
+                                       ftype = S1S;
+                                       break;
+                               case fsi2s_op:
+                                       func.b = fsi2s;
+                                       ftype = S1S;
+                                       break;
+                               case fui2s_op:
+                                       func.b = fui2s;
+                                       ftype = S1S;
+                                       break;
                                case fsqrts_op:
                                        func.b = fsqrts;
                                        ftype = S1S;
@@ -182,6 +206,30 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn)
                                        func.b = fd2s;
                                        ftype = D1S;
                                        break;
+                               case fd2si_op:
+                                       func.b = fd2si;
+                                       ftype = D1S;
+                                       break;
+                               case fd2si_z_op:
+                                       func.b = fd2si_z;
+                                       ftype = D1S;
+                                       break;
+                               case fd2ui_op:
+                                       func.b = fd2ui;
+                                       ftype = D1S;
+                                       break;
+                               case fd2ui_z_op:
+                                       func.b = fd2ui_z;
+                                       ftype = D1S;
+                                       break;
+                               case fsi2d_op:
+                                       func.b = fsi2d;
+                                       ftype = D1S;
+                                       break;
+                               case fui2d_op:
+                                       func.b = fui2d;
+                                       ftype = D1S;
+                                       break;
                                case fsqrtd_op:
                                        func.b = fsqrtd;
                                        ftype = D1D;
@@ -305,16 +353,16 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn)
         * If an exception is required, generate a tidy SIGFPE exception.
         */
 #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
-       if (((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE_NO_UDFE) ||
-           ((fpu_reg->fpcsr & FPCSR_mskUDF) && (fpu_reg->UDF_trap)))
+       if (((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE_NO_UDF_IEXE)
+           || ((fpu_reg->fpcsr << 5) & (fpu_reg->UDF_IEX_trap))) {
 #else
-       if ((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE)
+       if ((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE) {
 #endif
                return SIGFPE;
+       }
        return 0;
 }
 
-
 int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu)
 {
        unsigned long insn = 0, addr = regs->ipc;
@@ -336,6 +384,7 @@ int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu)
 
        if (NDS32Insn_OPCODE(insn) != cop0_op)
                return SIGILL;
+
        switch (NDS32Insn_OPCODE_COP0(insn)) {
        case fs1_op:
        case fs2_op:
diff --git a/arch/nds32/math-emu/fs2si.c b/arch/nds32/math-emu/fs2si.c
new file mode 100644 (file)
index 0000000..b4931d6
--- /dev/null
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2019 Andes Technology Corporation
+#include <linux/uaccess.h>
+
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+
+void fs2si(void *ft, void *fa)
+{
+       int r;
+
+       FP_DECL_S(A);
+       FP_DECL_EX;
+
+       FP_UNPACK_SP(A, fa);
+
+       if (A_c == FP_CLS_INF) {
+               *(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else if (A_c == FP_CLS_NAN) {
+               *(int *)ft = 0xffffffff;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else {
+               FP_TO_INT_ROUND_S(r, A, 32, 1);
+               __FPU_FPCSR |= FP_CUR_EXCEPTIONS;
+               *(int *)ft = r;
+       }
+}
diff --git a/arch/nds32/math-emu/fs2siz.c b/arch/nds32/math-emu/fs2siz.c
new file mode 100644 (file)
index 0000000..1c2b99c
--- /dev/null
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2019 Andes Technology Corporation
+#include <linux/uaccess.h>
+
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+
+void fs2si_z(void *ft, void *fa)
+{
+       int r;
+
+       FP_DECL_S(A);
+       FP_DECL_EX;
+
+       FP_UNPACK_SP(A, fa);
+
+       if (A_c == FP_CLS_INF) {
+               *(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else if (A_c == FP_CLS_NAN) {
+               *(int *)ft = 0xffffffff;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else {
+               FP_TO_INT_S(r, A, 32, 1);
+               __FPU_FPCSR |= FP_CUR_EXCEPTIONS;
+               *(int *)ft = r;
+       }
+}
diff --git a/arch/nds32/math-emu/fs2ui.c b/arch/nds32/math-emu/fs2ui.c
new file mode 100644 (file)
index 0000000..c337f03
--- /dev/null
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2019 Andes Technology Corporation
+#include <linux/uaccess.h>
+
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+
+void fs2ui(void *ft, void *fa)
+{
+       unsigned int r;
+
+       FP_DECL_S(A);
+       FP_DECL_EX;
+
+       FP_UNPACK_SP(A, fa);
+
+       if (A_c == FP_CLS_INF) {
+               *(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else if (A_c == FP_CLS_NAN) {
+               *(unsigned int *)ft = 0xffffffff;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else {
+               FP_TO_INT_ROUND_S(r, A, 32, 0);
+               __FPU_FPCSR |= FP_CUR_EXCEPTIONS;
+               *(unsigned int *)ft = r;
+       }
+}
diff --git a/arch/nds32/math-emu/fs2uiz.c b/arch/nds32/math-emu/fs2uiz.c
new file mode 100644 (file)
index 0000000..22c5e47
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2019 Andes Technology Corporation
+#include <linux/uaccess.h>
+
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+
+void fs2ui_z(void *ft, void *fa)
+{
+       unsigned int r;
+
+       FP_DECL_S(A);
+       FP_DECL_EX;
+
+       FP_UNPACK_SP(A, fa);
+
+       if (A_c == FP_CLS_INF) {
+               *(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else if (A_c == FP_CLS_NAN) {
+               *(unsigned int *)ft = 0xffffffff;
+               __FPU_FPCSR |= FP_EX_INVALID;
+       } else {
+               FP_TO_INT_S(r, A, 32, 0);
+               __FPU_FPCSR |= FP_CUR_EXCEPTIONS;
+               *(unsigned int *)ft = r;
+       }
+
+}
diff --git a/arch/nds32/math-emu/fsi2d.c b/arch/nds32/math-emu/fsi2d.c
new file mode 100644 (file)
index 0000000..6b04cec
--- /dev/null
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2019 Andes Technology Corporation
+#include <linux/uaccess.h>
+
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+
+void fsi2d(void *ft, void *fa)
+{
+       int a = *(int *)fa;
+
+       FP_DECL_D(R);
+       FP_DECL_EX;
+
+       FP_FROM_INT_D(R, a, 32, int);
+
+       FP_PACK_DP(ft, R);
+
+       __FPU_FPCSR |= FP_CUR_EXCEPTIONS;
+
+}
diff --git a/arch/nds32/math-emu/fsi2s.c b/arch/nds32/math-emu/fsi2s.c
new file mode 100644 (file)
index 0000000..689864a
--- /dev/null
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2019 Andes Technology Corporation
+#include <linux/uaccess.h>
+
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+
+void fsi2s(void *ft, void *fa)
+{
+       int a = *(int *)fa;
+
+       FP_DECL_S(R);
+       FP_DECL_EX;
+
+       FP_FROM_INT_S(R, a, 32, int);
+
+       FP_PACK_SP(ft, R);
+
+       __FPU_FPCSR |= FP_CUR_EXCEPTIONS;
+
+}
diff --git a/arch/nds32/math-emu/fui2d.c b/arch/nds32/math-emu/fui2d.c
new file mode 100644 (file)
index 0000000..9689d33
--- /dev/null
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2019 Andes Technology Corporation
+#include <linux/uaccess.h>
+
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+
+void fui2d(void *ft, void *fa)
+{
+       unsigned int a = *(unsigned int *)fa;
+
+       FP_DECL_D(R);
+       FP_DECL_EX;
+
+       FP_FROM_INT_D(R, a, 32, int);
+
+       FP_PACK_DP(ft, R);
+
+       __FPU_FPCSR |= FP_CUR_EXCEPTIONS;
+
+}
diff --git a/arch/nds32/math-emu/fui2s.c b/arch/nds32/math-emu/fui2s.c
new file mode 100644 (file)
index 0000000..f70f076
--- /dev/null
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2019 Andes Technology Corporation
+#include <linux/uaccess.h>
+
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+
+void fui2s(void *ft, void *fa)
+{
+       unsigned int a = *(unsigned int *)fa;
+
+       FP_DECL_S(R);
+       FP_DECL_EX;
+
+       FP_FROM_INT_S(R, a, 32, int);
+
+       FP_PACK_SP(ft, R);
+
+       __FPU_FPCSR |= FP_CUR_EXCEPTIONS;
+
+}
index 09407ed..4860efa 100644 (file)
@@ -36,7 +36,6 @@ config PARISC
        select GENERIC_STRNCPY_FROM_USER
        select SYSCTL_ARCH_UNALIGN_ALLOW
        select SYSCTL_EXCEPTION_TRACE
-       select ARCH_DISCARD_MEMBLOCK
        select HAVE_MOD_ARCH_SPECIFIC
        select VIRT_TO_BUS
        select MODULES_USE_ELF_RELA
@@ -195,7 +194,8 @@ config PREFETCH
 
 config MLONGCALLS
        bool "Enable the -mlong-calls compiler option for big kernels"
-       default y
+       default y if !MODULES || UBSAN || FTRACE
+       default n
        depends on PA8X00
        help
          If you configure the kernel to include many drivers built-in instead
index ccc1097..d3e3d94 100644 (file)
@@ -34,7 +34,6 @@ CONFIG_INET_DIAG=m
 CONFIG_NETFILTER=y
 CONFIG_LLC2=m
 CONFIG_NET_PKTGEN=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
index 5acb93d..a885949 100644 (file)
@@ -70,7 +70,6 @@ CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_LLC2=m
 CONFIG_NET_PKTGEN=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
index 83ffd16..0cae966 100644 (file)
@@ -24,7 +24,6 @@ CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
index 8d41a73..6c29b84 100644 (file)
@@ -32,7 +32,6 @@ CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
 CONFIG_NET_PKTGEN=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
index 900b000..507f064 100644 (file)
@@ -57,7 +57,6 @@ CONFIG_IP_DCCP=m
 CONFIG_TIPC=m
 CONFIG_LLC2=m
 CONFIG_DNS_RESOLVER=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
index 52c9050..6a91cc2 100644 (file)
@@ -44,7 +44,6 @@ CONFIG_INET6_AH=y
 CONFIG_INET6_ESP=y
 CONFIG_INET6_IPCOMP=y
 CONFIG_LLC2=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
index a8f9bbe..18b072a 100644 (file)
@@ -47,7 +47,6 @@ CONFIG_INET_ESP=m
 CONFIG_INET_DIAG=m
 CONFIG_LLC2=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
index 3d4dd68..a303ae9 100644 (file)
@@ -2,6 +2,30 @@
 #ifndef __PARISC_SPECIAL_INSNS_H
 #define __PARISC_SPECIAL_INSNS_H
 
+#define lpa(va)        ({                      \
+       unsigned long pa;               \
+       __asm__ __volatile__(           \
+               "copy %%r0,%0\n\t"      \
+               "lpa %%r0(%1),%0"       \
+               : "=r" (pa)             \
+               : "r" (va)              \
+               : "memory"              \
+       );                              \
+       pa;                             \
+})
+
+#define lpa_user(va)   ({              \
+       unsigned long pa;               \
+       __asm__ __volatile__(           \
+               "copy %%r0,%0\n\t"      \
+               "lpa %%r0(%%sr3,%1),%0" \
+               : "=r" (pa)             \
+               : "r" (va)              \
+               : "memory"              \
+       );                              \
+       pa;                             \
+})
+
 #define mfctl(reg)     ({              \
        unsigned long cr;               \
        __asm__ __volatile__(           \
index bf2274e..ca1f5ca 100644 (file)
@@ -56,7 +56,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
                 * time IO-PDIR is changed in Ike/Astro.
                 */
                if ((cond & ALT_COND_NO_IOC_FDC) &&
-                       (boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC))
+                       ((boot_cpu_data.cpu_type <= pcxw_) ||
+                        (boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC)))
                        continue;
 
                /* Want to replace pdtlb by a pdtlb,l instruction? */
index c3b1b9c..cd33b4f 100644 (file)
@@ -35,6 +35,15 @@ OUTPUT_FORMAT("elf64-hppa-linux")
 OUTPUT_ARCH(hppa:hppa2.0w)
 #endif
 
+#define EXIT_TEXT_SECTIONS()   .exit.text : { EXIT_TEXT }
+#if !defined(CONFIG_64BIT) || defined(CONFIG_MLONGCALLS)
+#define MLONGCALL_KEEP(x)
+#define MLONGCALL_DISCARD(x)   x
+#else
+#define MLONGCALL_KEEP(x)      x
+#define MLONGCALL_DISCARD(x)
+#endif
+
 ENTRY(parisc_kernel_start)
 #ifndef CONFIG_64BIT
 jiffies = jiffies_64 + 4;
@@ -47,15 +56,11 @@ SECTIONS
 
        __init_begin = .;
        HEAD_TEXT_SECTION
-       INIT_TEXT_SECTION(8)
+       MLONGCALL_DISCARD(INIT_TEXT_SECTION(8))
 
        . = ALIGN(PAGE_SIZE);
        INIT_DATA_SECTION(PAGE_SIZE)
-       /* we have to discard exit text and such at runtime, not link time */
-       .exit.text :
-       {
-               EXIT_TEXT
-       }
+       MLONGCALL_DISCARD(EXIT_TEXT_SECTIONS())
        .exit.data :
        {
                EXIT_DATA
@@ -73,11 +78,12 @@ SECTIONS
 
        _text = .;              /* Text and read-only data */
        _stext = .;
+       MLONGCALL_KEEP(INIT_TEXT_SECTION(8))
        .text ALIGN(PAGE_SIZE) : {
                TEXT_TEXT
+               LOCK_TEXT
                SCHED_TEXT
                CPUIDLE_TEXT
-               LOCK_TEXT
                KPROBES_TEXT
                IRQENTRY_TEXT
                SOFTIRQENTRY_TEXT
@@ -92,6 +98,7 @@ SECTIONS
                *(.lock.text)           /* out-of-line lock text */
                *(.gnu.warning)
        }
+       MLONGCALL_KEEP(EXIT_TEXT_SECTIONS())
        . = ALIGN(PAGE_SIZE);
        _etext = .;
        /* End of text section */
index bfcd834..ef783a3 100644 (file)
     ((exponent < (SGL_P - 1)) ?                                \
      (Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) : FALSE)
 
-#define Int_isinexact_to_sgl(int_value)        (int_value << 33 - SGL_EXP_LENGTH)
+#define Int_isinexact_to_sgl(int_value)        ((int_value << 33 - SGL_EXP_LENGTH) != 0)
 
 #define Sgl_roundnearest_from_int(int_value,sgl_value)                 \
     if (int_value & 1<<(SGL_EXP_LENGTH - 2))   /* round bit */         \
-       if ((int_value << 34 - SGL_EXP_LENGTH) || Slow(sgl_value))      \
+       if (((int_value << 34 - SGL_EXP_LENGTH) != 0) || Slow(sgl_value)) \
                Sall(sgl_value)++
 
 #define Dint_isinexact_to_sgl(dint_valueA,dint_valueB)         \
-    ((Dintp1(dint_valueA) << 33 - SGL_EXP_LENGTH) || Dintp2(dint_valueB))
+    (((Dintp1(dint_valueA) << 33 - SGL_EXP_LENGTH) != 0) || Dintp2(dint_valueB))
 
 #define Sgl_roundnearest_from_dint(dint_valueA,dint_valueB,sgl_value)  \
     if (Dintp1(dint_valueA) & 1<<(SGL_EXP_LENGTH - 2))                         \
-       if ((Dintp1(dint_valueA) << 34 - SGL_EXP_LENGTH) ||             \
+       if (((Dintp1(dint_valueA) << 34 - SGL_EXP_LENGTH) != 0) ||      \
        Dintp2(dint_valueB) || Slow(sgl_value)) Sall(sgl_value)++
 
 #define Dint_isinexact_to_dbl(dint_value)      \
index 80b12aa..426d5c3 100644 (file)
@@ -751,22 +751,32 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
        case BPF_ALU | BPF_ADD | BPF_X:
        case BPF_ALU64 | BPF_ADD | BPF_X:
                emit(is64 ? rv_add(rd, rd, rs) : rv_addw(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_SUB | BPF_X:
        case BPF_ALU64 | BPF_SUB | BPF_X:
                emit(is64 ? rv_sub(rd, rd, rs) : rv_subw(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_AND | BPF_X:
        case BPF_ALU64 | BPF_AND | BPF_X:
                emit(rv_and(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_OR | BPF_X:
        case BPF_ALU64 | BPF_OR | BPF_X:
                emit(rv_or(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_XOR | BPF_X:
        case BPF_ALU64 | BPF_XOR | BPF_X:
                emit(rv_xor(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_MUL | BPF_X:
        case BPF_ALU64 | BPF_MUL | BPF_X:
@@ -789,14 +799,20 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
        case BPF_ALU | BPF_LSH | BPF_X:
        case BPF_ALU64 | BPF_LSH | BPF_X:
                emit(is64 ? rv_sll(rd, rd, rs) : rv_sllw(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_RSH | BPF_X:
        case BPF_ALU64 | BPF_RSH | BPF_X:
                emit(is64 ? rv_srl(rd, rd, rs) : rv_srlw(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_ARSH | BPF_X:
        case BPF_ALU64 | BPF_ARSH | BPF_X:
                emit(is64 ? rv_sra(rd, rd, rs) : rv_sraw(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
 
        /* dst = -dst */
@@ -804,6 +820,8 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
        case BPF_ALU64 | BPF_NEG:
                emit(is64 ? rv_sub(rd, RV_REG_ZERO, rd) :
                     rv_subw(rd, RV_REG_ZERO, rd), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
 
        /* dst = BSWAP##imm(dst) */
@@ -958,14 +976,20 @@ out_be:
        case BPF_ALU | BPF_LSH | BPF_K:
        case BPF_ALU64 | BPF_LSH | BPF_K:
                emit(is64 ? rv_slli(rd, rd, imm) : rv_slliw(rd, rd, imm), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_RSH | BPF_K:
        case BPF_ALU64 | BPF_RSH | BPF_K:
                emit(is64 ? rv_srli(rd, rd, imm) : rv_srliw(rd, rd, imm), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_ARSH | BPF_K:
        case BPF_ALU64 | BPF_ARSH | BPF_K:
                emit(is64 ? rv_srai(rd, rd, imm) : rv_sraiw(rd, rd, imm), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
 
        /* JUMP off */
index 9a26b44..8e645dd 100644 (file)
@@ -356,6 +356,8 @@ static int get_vdev_port_node_info(struct mdesc_handle *md, u64 node,
 
        node_info->vdev_port.id = *idp;
        node_info->vdev_port.name = kstrdup_const(name, GFP_KERNEL);
+       if (!node_info->vdev_port.name)
+               return -1;
        node_info->vdev_port.parent_cfg_hdl = *parent_cfg_hdlp;
 
        return 0;
index 6de7c68..a58ae9c 100644 (file)
@@ -891,6 +891,10 @@ static int sparc_perf_event_set_period(struct perf_event *event,
        s64 period = hwc->sample_period;
        int ret = 0;
 
+       /* The period may have been changed by PERF_EVENT_IOC_PERIOD */
+       if (unlikely(period != hwc->last_period))
+               left = period - (hwc->last_period - left);
+
        if (unlikely(left <= -period)) {
                left = period;
                local64_set(&hwc->period_left, left);
index d245f89..d220b68 100644 (file)
@@ -587,7 +587,7 @@ xcall_flush_tlb_kernel_range:       /* 44 insns */
        sub             %g7, %g1, %g3
        srlx            %g3, 18, %g2
        brnz,pn         %g2, 2f
-        add            %g2, 1, %g2
+        sethi          %hi(PAGE_SIZE), %g2
        sub             %g3, %g2, %g3
        or              %g1, 0x20, %g1          ! Nucleus
 1:     stxa            %g0, [%g1 + %g3] ASI_DMMU_DEMAP
@@ -751,7 +751,7 @@ __cheetah_xcall_flush_tlb_kernel_range:     /* 44 insns */
        sub             %g7, %g1, %g3
        srlx            %g3, 18, %g2
        brnz,pn         %g2, 2f
-        add            %g2, 1, %g2
+        sethi          %hi(PAGE_SIZE), %g2
        sub             %g3, %g2, %g3
        or              %g1, 0x20, %g1          ! Nucleus
 1:     stxa            %g0, [%g1 + %g3] ASI_DMMU_DEMAP
index f03cb32..8b2a212 100644 (file)
@@ -152,8 +152,10 @@ static int hmac_init_tfm(struct crypto_tfm *tfm)
 
        parent->descsize = sizeof(struct shash_desc) +
                           crypto_shash_descsize(hash);
-       if (WARN_ON(parent->descsize > HASH_MAX_DESCSIZE))
+       if (WARN_ON(parent->descsize > HASH_MAX_DESCSIZE)) {
+               crypto_free_shash(hash);
                return -EINVAL;
+       }
 
        ctx->hash = hash;
        return 0;
index 6ea1a27..787dccc 100644 (file)
@@ -198,7 +198,7 @@ static void __exit jent_mod_exit(void)
        crypto_unregister_rng(&jent_alg);
 }
 
-subsys_initcall(jent_mod_init);
+module_init(jent_mod_init);
 module_exit(jent_mod_exit);
 
 MODULE_LICENSE("Dual BSD/GPL");
index 78dc07c..29f7b15 100644 (file)
@@ -409,27 +409,44 @@ static int rename_compat_devs(struct ib_device *device)
 
 int ib_device_rename(struct ib_device *ibdev, const char *name)
 {
+       unsigned long index;
+       void *client_data;
        int ret;
 
        down_write(&devices_rwsem);
        if (!strcmp(name, dev_name(&ibdev->dev))) {
-               ret = 0;
-               goto out;
+               up_write(&devices_rwsem);
+               return 0;
        }
 
        if (__ib_device_get_by_name(name)) {
-               ret = -EEXIST;
-               goto out;
+               up_write(&devices_rwsem);
+               return -EEXIST;
        }
 
        ret = device_rename(&ibdev->dev, name);
-       if (ret)
-               goto out;
+       if (ret) {
+               up_write(&devices_rwsem);
+               return ret;
+       }
+
        strlcpy(ibdev->name, name, IB_DEVICE_NAME_MAX);
        ret = rename_compat_devs(ibdev);
-out:
-       up_write(&devices_rwsem);
-       return ret;
+
+       downgrade_write(&devices_rwsem);
+       down_read(&ibdev->client_data_rwsem);
+       xan_for_each_marked(&ibdev->client_data, index, client_data,
+                           CLIENT_DATA_REGISTERED) {
+               struct ib_client *client = xa_load(&clients, index);
+
+               if (!client || !client->rename)
+                       continue;
+
+               client->rename(ibdev, client_data);
+       }
+       up_read(&ibdev->client_data_rwsem);
+       up_read(&devices_rwsem);
+       return 0;
 }
 
 static int alloc_name(struct ib_device *ibdev, const char *name)
@@ -474,14 +491,15 @@ static void ib_device_release(struct device *device)
 
        free_netdevs(dev);
        WARN_ON(refcount_read(&dev->refcount));
-       ib_cache_release_one(dev);
-       ib_security_release_port_pkey_list(dev);
-       xa_destroy(&dev->compat_devs);
-       xa_destroy(&dev->client_data);
-       if (dev->port_data)
+       if (dev->port_data) {
+               ib_cache_release_one(dev);
+               ib_security_release_port_pkey_list(dev);
                kfree_rcu(container_of(dev->port_data, struct ib_port_data_rcu,
                                       pdata[0]),
                          rcu_head);
+       }
+       xa_destroy(&dev->compat_devs);
+       xa_destroy(&dev->client_data);
        kfree_rcu(dev, rcu_head);
 }
 
@@ -1935,6 +1953,9 @@ static void free_netdevs(struct ib_device *ib_dev)
        unsigned long flags;
        unsigned int port;
 
+       if (!ib_dev->port_data)
+               return;
+
        rdma_for_each_port (ib_dev, port) {
                struct ib_port_data *pdata = &ib_dev->port_data[port];
                struct net_device *ndev;
index 5445323..e63fbda 100644 (file)
@@ -110,6 +110,8 @@ int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx);
 void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile);
 void release_ufile_idr_uobject(struct ib_uverbs_file *ufile);
 
+struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs);
+
 /*
  * This is the runtime description of the uverbs API, used by the syscall
  * machinery to validate and dispatch calls.
index 5a3a178..63fe14c 100644 (file)
@@ -174,6 +174,17 @@ static int uverbs_request_finish(struct uverbs_req_iter *iter)
        return 0;
 }
 
+/*
+ * When calling a destroy function during an error unwind we need to pass in
+ * the udata that is sanitized of all user arguments. Ie from the driver
+ * perspective it looks like no udata was passed.
+ */
+struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs)
+{
+       attrs->driver_udata = (struct ib_udata){};
+       return &attrs->driver_udata;
+}
+
 static struct ib_uverbs_completion_event_file *
 _ib_uverbs_lookup_comp_file(s32 fd, struct uverbs_attr_bundle *attrs)
 {
@@ -441,7 +452,7 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs)
        return uobj_alloc_commit(uobj, attrs);
 
 err_copy:
-       ib_dealloc_pd_user(pd, &attrs->driver_udata);
+       ib_dealloc_pd_user(pd, uverbs_get_cleared_udata(attrs));
        pd = NULL;
 err_alloc:
        kfree(pd);
@@ -644,7 +655,7 @@ err_copy:
        }
 
 err_dealloc_xrcd:
-       ib_dealloc_xrcd(xrcd, &attrs->driver_udata);
+       ib_dealloc_xrcd(xrcd, uverbs_get_cleared_udata(attrs));
 
 err:
        uobj_alloc_abort(&obj->uobject, attrs);
@@ -767,7 +778,7 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs)
        return uobj_alloc_commit(uobj, attrs);
 
 err_copy:
-       ib_dereg_mr_user(mr, &attrs->driver_udata);
+       ib_dereg_mr_user(mr, uverbs_get_cleared_udata(attrs));
 
 err_put:
        uobj_put_obj_read(pd);
@@ -1042,7 +1053,7 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs,
        return obj;
 
 err_cb:
-       ib_destroy_cq(cq);
+       ib_destroy_cq_user(cq, uverbs_get_cleared_udata(attrs));
 
 err_file:
        if (ev_file)
@@ -1478,7 +1489,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
 
        return uobj_alloc_commit(&obj->uevent.uobject, attrs);
 err_cb:
-       ib_destroy_qp(qp);
+       ib_destroy_qp_user(qp, uverbs_get_cleared_udata(attrs));
 
 err_put:
        if (!IS_ERR(xrcd_uobj))
@@ -1611,7 +1622,7 @@ static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs)
        return uobj_alloc_commit(&obj->uevent.uobject, attrs);
 
 err_destroy:
-       ib_destroy_qp(qp);
+       ib_destroy_qp_user(qp, uverbs_get_cleared_udata(attrs));
 err_xrcd:
        uobj_put_read(xrcd_uobj);
 err_put:
@@ -2453,7 +2464,8 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs)
        return uobj_alloc_commit(uobj, attrs);
 
 err_copy:
-       rdma_destroy_ah(ah, RDMA_DESTROY_AH_SLEEPABLE);
+       rdma_destroy_ah_user(ah, RDMA_DESTROY_AH_SLEEPABLE,
+                            uverbs_get_cleared_udata(attrs));
 
 err_put:
        uobj_put_obj_read(pd);
@@ -2964,7 +2976,7 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs)
        return uobj_alloc_commit(&obj->uevent.uobject, attrs);
 
 err_copy:
-       ib_destroy_wq(wq, &attrs->driver_udata);
+       ib_destroy_wq(wq, uverbs_get_cleared_udata(attrs));
 err_put_cq:
        uobj_put_obj_read(cq);
 err_put_pd:
@@ -3464,7 +3476,7 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs,
        return uobj_alloc_commit(&obj->uevent.uobject, attrs);
 
 err_copy:
-       ib_destroy_srq_user(srq, &attrs->driver_udata);
+       ib_destroy_srq_user(srq, uverbs_get_cleared_udata(attrs));
 
 err_free:
        kfree(srq);
index db5c46a..07ea4e3 100644 (file)
@@ -135,7 +135,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(
 
        return 0;
 err_cq:
-       ib_destroy_cq(cq);
+       ib_destroy_cq_user(cq, uverbs_get_cleared_udata(attrs));
 
 err_event_file:
        if (ev_file)
index 610d3b9..997f7a3 100644 (file)
@@ -148,7 +148,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_DM_MR_REG)(
        return 0;
 
 err_dereg:
-       ib_dereg_mr_user(mr, &attrs->driver_udata);
+       ib_dereg_mr_user(mr, uverbs_get_cleared_udata(attrs));
 
        return ret;
 }
index 6d6886c..0fea5d6 100644 (file)
@@ -1728,7 +1728,6 @@ int efa_mmap(struct ib_ucontext *ibucontext,
                ibdev_dbg(&dev->ibdev, "Mapping executable pages is not permitted\n");
                return -EPERM;
        }
-       vma->vm_flags &= ~VM_MAYEXEC;
 
        return __efa_mmap(dev, ucontext, vma, key, length);
 }
index 310105d..4221a99 100644 (file)
@@ -9850,6 +9850,7 @@ void hfi1_quiet_serdes(struct hfi1_pportdata *ppd)
 
        /* disable the port */
        clear_rcvctrl(dd, RCV_CTRL_RCV_PORT_ENABLE_SMASK);
+       cancel_work_sync(&ppd->freeze_work);
 }
 
 static inline int init_cpu_counters(struct hfi1_devdata *dd)
index 0cd71ce..3592a9e 100644 (file)
@@ -324,6 +324,9 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
        u32 *tidlist = NULL;
        struct tid_user_buf *tidbuf;
 
+       if (!PAGE_ALIGNED(tinfo->vaddr))
+               return -EINVAL;
+
        tidbuf = kzalloc(sizeof(*tidbuf), GFP_KERNEL);
        if (!tidbuf)
                return -ENOMEM;
index 1eb4105..a2b26a6 100644 (file)
@@ -1356,8 +1356,6 @@ static void hfi1_fill_device_attr(struct hfi1_devdata *dd)
        rdi->dparms.props.max_cq = hfi1_max_cqs;
        rdi->dparms.props.max_ah = hfi1_max_ahs;
        rdi->dparms.props.max_cqe = hfi1_max_cqes;
-       rdi->dparms.props.max_mr = rdi->lkey_table.max;
-       rdi->dparms.props.max_fmr = rdi->lkey_table.max;
        rdi->dparms.props.max_map_per_fmr = 32767;
        rdi->dparms.props.max_pd = hfi1_max_pds;
        rdi->dparms.props.max_qp_rd_atom = HFI1_MAX_RDMA_ATOMIC;
index 4c5d0f1..e068a02 100644 (file)
@@ -899,6 +899,7 @@ static void hns_roce_v1_release_lp_qp(struct hns_roce_dev *hr_dev)
                dev_err(dev, "Destroy cq for mr_free failed(%d)!\n", ret);
 
        hns_roce_dealloc_pd(&free_mr->mr_free_pd->ibpd, NULL);
+       kfree(&free_mr->mr_free_pd->ibpd);
 }
 
 static int hns_roce_db_init(struct hns_roce_dev *hr_dev)
index e3ec79b..6c86450 100644 (file)
@@ -190,12 +190,12 @@ int mlx5_cmd_alloc_sw_icm(struct mlx5_dm *dm, int type, u64 length,
                          u16 uid, phys_addr_t *addr, u32 *obj_id)
 {
        struct mlx5_core_dev *dev = dm->dev;
-       u32 num_blocks = DIV_ROUND_UP(length, MLX5_SW_ICM_BLOCK_SIZE(dev));
        u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
        u32 in[MLX5_ST_SZ_DW(create_sw_icm_in)] = {};
        unsigned long *block_map;
        u64 icm_start_addr;
        u32 log_icm_size;
+       u32 num_blocks;
        u32 max_blocks;
        u64 block_idx;
        void *sw_icm;
@@ -224,6 +224,8 @@ int mlx5_cmd_alloc_sw_icm(struct mlx5_dm *dm, int type, u64 length,
                return -EINVAL;
        }
 
+       num_blocks = (length + MLX5_SW_ICM_BLOCK_SIZE(dev) - 1) >>
+                    MLX5_LOG_SW_ICM_BLOCK_SIZE(dev);
        max_blocks = BIT(log_icm_size - MLX5_LOG_SW_ICM_BLOCK_SIZE(dev));
        spin_lock(&dm->lock);
        block_idx = bitmap_find_next_zero_area(block_map,
@@ -266,13 +268,16 @@ int mlx5_cmd_dealloc_sw_icm(struct mlx5_dm *dm, int type, u64 length,
                            u16 uid, phys_addr_t addr, u32 obj_id)
 {
        struct mlx5_core_dev *dev = dm->dev;
-       u32 num_blocks = DIV_ROUND_UP(length, MLX5_SW_ICM_BLOCK_SIZE(dev));
        u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
        u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
        unsigned long *block_map;
+       u32 num_blocks;
        u64 start_idx;
        int err;
 
+       num_blocks = (length + MLX5_SW_ICM_BLOCK_SIZE(dev) - 1) >>
+                    MLX5_LOG_SW_ICM_BLOCK_SIZE(dev);
+
        switch (type) {
        case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
                start_idx =
index abac70a..340290b 100644 (file)
@@ -2344,7 +2344,7 @@ static int handle_alloc_dm_sw_icm(struct ib_ucontext *ctx,
        /* Allocation size must a multiple of the basic block size
         * and a power of 2.
         */
-       act_size = roundup(attr->length, MLX5_SW_ICM_BLOCK_SIZE(dm_db->dev));
+       act_size = round_up(attr->length, MLX5_SW_ICM_BLOCK_SIZE(dm_db->dev));
        act_size = roundup_pow_of_two(act_size);
 
        dm->size = act_size;
index 5ff32d3..2c4e569 100644 (file)
@@ -1459,8 +1459,6 @@ static void qib_fill_device_attr(struct qib_devdata *dd)
        rdi->dparms.props.max_cq = ib_qib_max_cqs;
        rdi->dparms.props.max_cqe = ib_qib_max_cqes;
        rdi->dparms.props.max_ah = ib_qib_max_ahs;
-       rdi->dparms.props.max_mr = rdi->lkey_table.max;
-       rdi->dparms.props.max_fmr = rdi->lkey_table.max;
        rdi->dparms.props.max_map_per_fmr = 32767;
        rdi->dparms.props.max_qp_rd_atom = QIB_MAX_RDMA_ATOMIC;
        rdi->dparms.props.max_qp_init_rd_atom = 255;
index 54f3f9c..f48240f 100644 (file)
@@ -96,6 +96,8 @@ int rvt_driver_mr_init(struct rvt_dev_info *rdi)
        for (i = 0; i < rdi->lkey_table.max; i++)
                RCU_INIT_POINTER(rdi->lkey_table.table[i], NULL);
 
+       rdi->dparms.props.max_mr = rdi->lkey_table.max;
+       rdi->dparms.props.max_fmr = rdi->lkey_table.max;
        return 0;
 }
 
index 31a2e65..c5a5061 100644 (file)
@@ -594,7 +594,8 @@ static int alloc_qpn(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt,
                        offset = qpt->incr | ((offset & 1) ^ 1);
                }
                /* there can be no set bits in low-order QoS bits */
-               WARN_ON(offset & (BIT(rdi->dparms.qos_shift) - 1));
+               WARN_ON(rdi->dparms.qos_shift > 1 &&
+                       offset & ((BIT(rdi->dparms.qos_shift - 1) - 1) << 1));
                qpn = mk_qpn(qpt, map, offset);
        }
 
index be9ddca..4305da2 100644 (file)
@@ -148,6 +148,7 @@ MODULE_PARM_DESC(ch_count,
 
 static void srp_add_one(struct ib_device *device);
 static void srp_remove_one(struct ib_device *device, void *client_data);
+static void srp_rename_dev(struct ib_device *device, void *client_data);
 static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc);
 static void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc,
                const char *opname);
@@ -162,7 +163,8 @@ static struct workqueue_struct *srp_remove_wq;
 static struct ib_client srp_client = {
        .name   = "srp",
        .add    = srp_add_one,
-       .remove = srp_remove_one
+       .remove = srp_remove_one,
+       .rename = srp_rename_dev
 };
 
 static struct ib_sa_client srp_sa_client;
@@ -4112,6 +4114,20 @@ free_host:
        return NULL;
 }
 
+static void srp_rename_dev(struct ib_device *device, void *client_data)
+{
+       struct srp_device *srp_dev = client_data;
+       struct srp_host *host, *tmp_host;
+
+       list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
+               char name[IB_DEVICE_NAME_MAX + 8];
+
+               snprintf(name, sizeof(name), "srp-%s-%d",
+                        dev_name(&device->dev), host->port);
+               device_rename(&host->dev, name);
+       }
+}
+
 static void srp_add_one(struct ib_device *device)
 {
        struct srp_device *srp_dev;
index 1c66fb2..f2fe344 100644 (file)
 #define FLEXCAN_MB_CNT_LENGTH(x)       (((x) & 0xf) << 16)
 #define FLEXCAN_MB_CNT_TIMESTAMP(x)    ((x) & 0xffff)
 
-#define FLEXCAN_TIMEOUT_US             (50)
+#define FLEXCAN_TIMEOUT_US             (250)
 
 /* FLEXCAN hardware feature flags
  *
@@ -1583,9 +1583,6 @@ static int flexcan_probe(struct platform_device *pdev)
                        dev_dbg(&pdev->dev, "failed to setup stop-mode\n");
        }
 
-       dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
-                priv->regs, dev->irq);
-
        return 0;
 
  failed_register:
index 9b44940..deb274a 100644 (file)
@@ -822,6 +822,27 @@ static int m_can_poll(struct napi_struct *napi, int quota)
        if (!irqstatus)
                goto end;
 
+       /* Errata workaround for issue "Needless activation of MRAF irq"
+        * During frame reception while the MCAN is in Error Passive state
+        * and the Receive Error Counter has the value MCAN_ECR.REC = 127,
+        * it may happen that MCAN_IR.MRAF is set although there was no
+        * Message RAM access failure.
+        * If MCAN_IR.MRAF is enabled, an interrupt to the Host CPU is generated
+        * The Message RAM Access Failure interrupt routine needs to check
+        * whether MCAN_ECR.RP = â€™1’ and MCAN_ECR.REC = 127.
+        * In this case, reset MCAN_IR.MRAF. No further action is required.
+        */
+       if ((priv->version <= 31) && (irqstatus & IR_MRAF) &&
+           (m_can_read(priv, M_CAN_ECR) & ECR_RP)) {
+               struct can_berr_counter bec;
+
+               __m_can_get_berr_counter(dev, &bec);
+               if (bec.rxerr == 127) {
+                       m_can_write(priv, M_CAN_IR, IR_MRAF);
+                       irqstatus &= ~IR_MRAF;
+               }
+       }
+
        psr = m_can_read(priv, M_CAN_PSR);
        if (irqstatus & IR_ERR_STATE)
                work_done += m_can_handle_state_errors(dev, psr);
index 2e7e535..1c50788 100644 (file)
@@ -9,9 +9,10 @@ config CAN_HI311X
          Driver for the Holt HI311x SPI CAN controllers.
 
 config CAN_MCP251X
-       tristate "Microchip MCP251x SPI CAN controllers"
+       tristate "Microchip MCP251x and MCP25625 SPI CAN controllers"
        depends on HAS_DMA
        ---help---
-         Driver for the Microchip MCP251x SPI CAN controllers.
+         Driver for the Microchip MCP251x and MCP25625 SPI CAN
+         controllers.
 
 endmenu
index e908176..da64e71 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * CAN bus driver for Microchip 251x CAN Controller with SPI Interface
+ * CAN bus driver for Microchip 251x/25625 CAN Controller with SPI Interface
  *
  * MCP2510 support and bug fixes by Christian Pellegrin
  * <chripell@evolware.org>
@@ -41,7 +41,7 @@
  * static struct spi_board_info spi_board_info[] = {
  *         {
  *                 .modalias = "mcp2510",
- *                     // or "mcp2515" depending on your controller
+ *                     // "mcp2515" or "mcp25625" depending on your controller
  *                 .platform_data = &mcp251x_info,
  *                 .irq = IRQ_EINT13,
  *                 .max_speed_hz = 2*1000*1000,
@@ -238,6 +238,7 @@ static const struct can_bittiming_const mcp251x_bittiming_const = {
 enum mcp251x_model {
        CAN_MCP251X_MCP2510     = 0x2510,
        CAN_MCP251X_MCP2515     = 0x2515,
+       CAN_MCP251X_MCP25625    = 0x25625,
 };
 
 struct mcp251x_priv {
@@ -280,7 +281,6 @@ static inline int mcp251x_is_##_model(struct spi_device *spi) \
 }
 
 MCP251X_IS(2510);
-MCP251X_IS(2515);
 
 static void mcp251x_clean(struct net_device *net)
 {
@@ -639,7 +639,7 @@ static int mcp251x_hw_reset(struct spi_device *spi)
 
        /* Wait for oscillator startup timer after reset */
        mdelay(MCP251X_OST_DELAY_MS);
-       
+
        reg = mcp251x_read_reg(spi, CANSTAT);
        if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF)
                return -ENODEV;
@@ -820,9 +820,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
                /* receive buffer 0 */
                if (intf & CANINTF_RX0IF) {
                        mcp251x_hw_rx(spi, 0);
-                       /*
-                        * Free one buffer ASAP
-                        * (The MCP2515 does this automatically.)
+                       /* Free one buffer ASAP
+                        * (The MCP2515/25625 does this automatically.)
                         */
                        if (mcp251x_is_2510(spi))
                                mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00);
@@ -831,7 +830,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
                /* receive buffer 1 */
                if (intf & CANINTF_RX1IF) {
                        mcp251x_hw_rx(spi, 1);
-                       /* the MCP2515 does this automatically */
+                       /* The MCP2515/25625 does this automatically. */
                        if (mcp251x_is_2510(spi))
                                clear_intf |= CANINTF_RX1IF;
                }
@@ -1006,6 +1005,10 @@ static const struct of_device_id mcp251x_of_match[] = {
                .compatible     = "microchip,mcp2515",
                .data           = (void *)CAN_MCP251X_MCP2515,
        },
+       {
+               .compatible     = "microchip,mcp25625",
+               .data           = (void *)CAN_MCP251X_MCP25625,
+       },
        { }
 };
 MODULE_DEVICE_TABLE(of, mcp251x_of_match);
@@ -1019,6 +1022,10 @@ static const struct spi_device_id mcp251x_id_table[] = {
                .name           = "mcp2515",
                .driver_data    = (kernel_ulong_t)CAN_MCP251X_MCP2515,
        },
+       {
+               .name           = "mcp25625",
+               .driver_data    = (kernel_ulong_t)CAN_MCP251X_MCP25625,
+       },
        { }
 };
 MODULE_DEVICE_TABLE(spi, mcp251x_id_table);
@@ -1259,5 +1266,5 @@ module_spi_driver(mcp251x_can_driver);
 
 MODULE_AUTHOR("Chris Elston <celston@katalix.com>, "
              "Christian Pellegrin <chripell@evolware.org>");
-MODULE_DESCRIPTION("Microchip 251x CAN driver");
+MODULE_DESCRIPTION("Microchip 251x/25625 CAN driver");
 MODULE_LICENSE("GPL v2");
index ac3522b..4b3d0dd 100644 (file)
@@ -102,12 +102,6 @@ config CAN_PEAK_USB
 
          (see also http://www.peak-system.com).
 
-config CAN_MCBA_USB
-       tristate "Microchip CAN BUS Analyzer interface"
-       ---help---
-         This driver supports the CAN BUS Analyzer interface
-         from Microchip (http://www.microchip.com/development-tools/).
-
 config CAN_UCAN
        tristate "Theobroma Systems UCAN interface"
        ---help---
index f202440..63203ff 100644 (file)
@@ -1435,7 +1435,7 @@ static const struct xcan_devtype_data xcan_canfd_data = {
                 XCAN_FLAG_RXMNF |
                 XCAN_FLAG_TX_MAILBOXES |
                 XCAN_FLAG_RX_FIFO_MULTI,
-       .bittiming_const = &xcan_bittiming_const,
+       .bittiming_const = &xcan_bittiming_const_canfd,
        .btr_ts2_shift = XCAN_BTR_TS2_SHIFT_CANFD,
        .btr_sjw_shift = XCAN_BTR_SJW_SHIFT_CANFD,
        .bus_clk_name = "s_axi_aclk",
index 42da3f1..063c7a6 100644 (file)
@@ -1388,7 +1388,7 @@ static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
        int err;
 
        if (!vid)
-               return -EINVAL;
+               return -EOPNOTSUPP;
 
        entry->vid = vid - 1;
        entry->valid = false;
index 0663b78..1c3959e 100644 (file)
@@ -652,16 +652,6 @@ static int sja1105_speed[] = {
        [SJA1105_SPEED_1000MBPS] = 1000,
 };
 
-static sja1105_speed_t sja1105_get_speed_cfg(unsigned int speed_mbps)
-{
-       int i;
-
-       for (i = SJA1105_SPEED_AUTO; i <= SJA1105_SPEED_1000MBPS; i++)
-               if (sja1105_speed[i] == speed_mbps)
-                       return i;
-       return -EINVAL;
-}
-
 /* Set link speed and enable/disable traffic I/O in the MAC configuration
  * for a specific port.
  *
@@ -684,8 +674,21 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
        mii = priv->static_config.tables[BLK_IDX_XMII_PARAMS].entries;
        mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;
 
-       speed = sja1105_get_speed_cfg(speed_mbps);
-       if (speed_mbps && speed < 0) {
+       switch (speed_mbps) {
+       case 0:
+               /* No speed update requested */
+               speed = SJA1105_SPEED_AUTO;
+               break;
+       case 10:
+               speed = SJA1105_SPEED_10MBPS;
+               break;
+       case 100:
+               speed = SJA1105_SPEED_100MBPS;
+               break;
+       case 1000:
+               speed = SJA1105_SPEED_1000MBPS;
+               break;
+       default:
                dev_err(dev, "Invalid speed %iMbps\n", speed_mbps);
                return -EINVAL;
        }
@@ -695,10 +698,7 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
         * and we no longer need to store it in the static config (already told
         * hardware we want auto during upload phase).
         */
-       if (speed_mbps)
-               mac[port].speed = speed;
-       else
-               mac[port].speed = SJA1105_SPEED_AUTO;
+       mac[port].speed = speed;
 
        /* On P/Q/R/S, one can read from the device via the MAC reconfiguration
         * tables. On E/T, MAC reconfig tables are not readable, only writable.
index bb09319..2a3e245 100644 (file)
@@ -50,7 +50,7 @@ config XSURF100
        tristate "Amiga XSurf 100 AX88796/NE2000 clone support"
        depends on ZORRO
        select AX88796
-       select ASIX_PHY
+       select AX88796B_PHY
        help
          This driver is for the Individual Computers X-Surf 100 Ethernet
          card (based on the Asix AX88796 chip). If you have such a card,
index 1208f7e..3fc41da 100644 (file)
@@ -335,13 +335,13 @@ static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
 {
        u32 val;
        int err = 0;
-       bool is_locked;
 
-       is_locked = hw_atl_sem_ram_get(self);
-       if (!is_locked) {
-               err = -ETIME;
+       err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self,
+                                       val, val == 1U,
+                                       10U, 100000U);
+       if (err < 0)
                goto err_exit;
-       }
+
        if (IS_CHIP_FEATURE(REVISION_B1)) {
                u32 offset = 0;
 
@@ -353,8 +353,8 @@ static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
                        /* 1000 times by 10us = 10ms */
                        err = readx_poll_timeout_atomic(hw_atl_scrpad12_get,
                                                        self, val,
-                                                       (val & 0xF0000000) ==
-                                                        0x80000000,
+                                                       (val & 0xF0000000) !=
+                                                       0x80000000,
                                                        10U, 10000U);
                }
        } else {
index fbc9d6a..9c16d85 100644 (file)
@@ -384,7 +384,7 @@ static int aq_fw2x_set_sleep_proxy(struct aq_hw_s *self, u8 *mac)
        err = readx_poll_timeout_atomic(aq_fw2x_state2_get,
                                        self, val,
                                        val & HW_ATL_FW2X_CTRL_SLEEP_PROXY,
-                                       1U, 10000U);
+                                       1U, 100000U);
 
 err_exit:
        return err;
@@ -404,6 +404,8 @@ static int aq_fw2x_set_wol_params(struct aq_hw_s *self, u8 *mac)
 
        msg = (struct fw2x_msg_wol *)rpc;
 
+       memset(msg, 0, sizeof(*msg));
+
        msg->msg_id = HAL_ATLANTIC_UTILS_FW2X_MSG_WOL;
        msg->magic_packet_enabled = true;
        memcpy(msg->hw_addr, mac, ETH_ALEN);
index d1df0a4..717fccc 100644 (file)
@@ -335,6 +335,7 @@ static int __lb_setup(struct net_device *ndev,
 static int __lb_up(struct net_device *ndev,
                   enum hnae_loop loop_mode)
 {
+#define NIC_LB_TEST_WAIT_PHY_LINK_TIME 300
        struct hns_nic_priv *priv = netdev_priv(ndev);
        struct hnae_handle *h = priv->ae_handle;
        int speed, duplex;
@@ -361,6 +362,9 @@ static int __lb_up(struct net_device *ndev,
 
        h->dev->ops->adjust_link(h, speed, duplex);
 
+       /* wait adjust link done and phy ready */
+       msleep(NIC_LB_TEST_WAIT_PHY_LINK_TIME);
+
        return 0;
 }
 
index 7a67e23..d8e5241 100644 (file)
@@ -1304,8 +1304,8 @@ static void mvpp2_ethtool_get_strings(struct net_device *netdev, u32 sset,
                int i;
 
                for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_regs); i++)
-                       memcpy(data + i * ETH_GSTRING_LEN,
-                              &mvpp2_ethtool_regs[i].string, ETH_GSTRING_LEN);
+                       strscpy(data + i * ETH_GSTRING_LEN,
+                               mvpp2_ethtool_regs[i].string, ETH_GSTRING_LEN);
        }
 }
 
index f9fbb3f..765cd56 100644 (file)
@@ -1778,6 +1778,7 @@ static void mtk_poll_controller(struct net_device *dev)
 
 static int mtk_start_dma(struct mtk_eth *eth)
 {
+       u32 rx_2b_offset = (NET_IP_ALIGN == 2) ? MTK_RX_2B_OFFSET : 0;
        int err;
 
        err = mtk_dma_init(eth);
@@ -1794,7 +1795,7 @@ static int mtk_start_dma(struct mtk_eth *eth)
                MTK_QDMA_GLO_CFG);
 
        mtk_w32(eth,
-               MTK_RX_DMA_EN | MTK_RX_2B_OFFSET |
+               MTK_RX_DMA_EN | rx_2b_offset |
                MTK_RX_BT_32DWORDS | MTK_MULTI_EN,
                MTK_PDMA_GLO_CFG);
 
@@ -2298,13 +2299,13 @@ static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
 
        switch (cmd->cmd) {
        case ETHTOOL_GRXRINGS:
-               if (dev->features & NETIF_F_LRO) {
+               if (dev->hw_features & NETIF_F_LRO) {
                        cmd->data = MTK_MAX_RX_RING_NUM;
                        ret = 0;
                }
                break;
        case ETHTOOL_GRXCLSRLCNT:
-               if (dev->features & NETIF_F_LRO) {
+               if (dev->hw_features & NETIF_F_LRO) {
                        struct mtk_mac *mac = netdev_priv(dev);
 
                        cmd->rule_cnt = mac->hwlro_ip_cnt;
@@ -2312,11 +2313,11 @@ static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
                }
                break;
        case ETHTOOL_GRXCLSRULE:
-               if (dev->features & NETIF_F_LRO)
+               if (dev->hw_features & NETIF_F_LRO)
                        ret = mtk_hwlro_get_fdir_entry(dev, cmd);
                break;
        case ETHTOOL_GRXCLSRLALL:
-               if (dev->features & NETIF_F_LRO)
+               if (dev->hw_features & NETIF_F_LRO)
                        ret = mtk_hwlro_get_fdir_all(dev, cmd,
                                                     rule_locs);
                break;
@@ -2333,11 +2334,11 @@ static int mtk_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
 
        switch (cmd->cmd) {
        case ETHTOOL_SRXCLSRLINS:
-               if (dev->features & NETIF_F_LRO)
+               if (dev->hw_features & NETIF_F_LRO)
                        ret = mtk_hwlro_add_ipaddr(dev, cmd);
                break;
        case ETHTOOL_SRXCLSRLDEL:
-               if (dev->features & NETIF_F_LRO)
+               if (dev->hw_features & NETIF_F_LRO)
                        ret = mtk_hwlro_del_ipaddr(dev, cmd);
                break;
        default:
index a4a7ec0..6d1c9eb 100644 (file)
@@ -643,7 +643,7 @@ void cpsw_get_ringparam(struct net_device *ndev,
        struct cpsw_common *cpsw = priv->cpsw;
 
        /* not supported */
-       ering->tx_max_pending = 0;
+       ering->tx_max_pending = cpsw->descs_pool_size - CPSW_MAX_QUEUES;
        ering->tx_pending = cpdma_get_num_tx_descs(cpsw->dma);
        ering->rx_max_pending = cpsw->descs_pool_size - CPSW_MAX_QUEUES;
        ering->rx_pending = cpdma_get_num_rx_descs(cpsw->dma);
index cf38c39..1c96bed 100644 (file)
@@ -107,7 +107,7 @@ static void ipvlan_port_destroy(struct net_device *dev)
 }
 
 #define IPVLAN_FEATURES \
-       (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
+       (NETIF_F_SG | NETIF_F_CSUM_MASK | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
         NETIF_F_GSO | NETIF_F_TSO | NETIF_F_GSO_ROBUST | \
         NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \
         NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER)
index f99f278..1d406c6 100644 (file)
@@ -254,7 +254,7 @@ config AQUANTIA_PHY
        ---help---
          Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405
 
-config ASIX_PHY
+config AX88796B_PHY
        tristate "Asix PHYs"
        help
          Currently supports the Asix Electronics PHY found in the X-Surf 100
index 27d7f9f..5b5c866 100644 (file)
@@ -52,7 +52,7 @@ ifdef CONFIG_HWMON
 aquantia-objs                  += aquantia_hwmon.o
 endif
 obj-$(CONFIG_AQUANTIA_PHY)     += aquantia.o
-obj-$(CONFIG_ASIX_PHY)         += asix.o
+obj-$(CONFIG_AX88796B_PHY)     += ax88796b.o
 obj-$(CONFIG_AT803X_PHY)       += at803x.o
 obj-$(CONFIG_BCM63XX_PHY)      += bcm63xx.o
 obj-$(CONFIG_BCM7XXX_PHY)      += bcm7xxx.o
diff --git a/drivers/net/phy/asix.c b/drivers/net/phy/asix.c
deleted file mode 100644 (file)
index 79bf7ef..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/* Driver for Asix PHYs
- *
- * Author: Michael Schmitz <schmitzmic@gmail.com>
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mii.h>
-#include <linux/phy.h>
-
-#define PHY_ID_ASIX_AX88796B           0x003b1841
-
-MODULE_DESCRIPTION("Asix PHY driver");
-MODULE_AUTHOR("Michael Schmitz <schmitzmic@gmail.com>");
-MODULE_LICENSE("GPL");
-
-/**
- * asix_soft_reset - software reset the PHY via BMCR_RESET bit
- * @phydev: target phy_device struct
- *
- * Description: Perform a software PHY reset using the standard
- * BMCR_RESET bit and poll for the reset bit to be cleared.
- * Toggle BMCR_RESET bit off to accommodate broken AX8796B PHY implementation
- * such as used on the Individual Computers' X-Surf 100 Zorro card.
- *
- * Returns: 0 on success, < 0 on failure
- */
-static int asix_soft_reset(struct phy_device *phydev)
-{
-       int ret;
-
-       /* Asix PHY won't reset unless reset bit toggles */
-       ret = phy_write(phydev, MII_BMCR, 0);
-       if (ret < 0)
-               return ret;
-
-       return genphy_soft_reset(phydev);
-}
-
-static struct phy_driver asix_driver[] = { {
-       .phy_id         = PHY_ID_ASIX_AX88796B,
-       .name           = "Asix Electronics AX88796B",
-       .phy_id_mask    = 0xfffffff0,
-       /* PHY_BASIC_FEATURES */
-       .soft_reset     = asix_soft_reset,
-} };
-
-module_phy_driver(asix_driver);
-
-static struct mdio_device_id __maybe_unused asix_tbl[] = {
-       { PHY_ID_ASIX_AX88796B, 0xfffffff0 },
-       { }
-};
-
-MODULE_DEVICE_TABLE(mdio, asix_tbl);
diff --git a/drivers/net/phy/ax88796b.c b/drivers/net/phy/ax88796b.c
new file mode 100644 (file)
index 0000000..79bf7ef
--- /dev/null
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Driver for Asix PHYs
+ *
+ * Author: Michael Schmitz <schmitzmic@gmail.com>
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#define PHY_ID_ASIX_AX88796B           0x003b1841
+
+MODULE_DESCRIPTION("Asix PHY driver");
+MODULE_AUTHOR("Michael Schmitz <schmitzmic@gmail.com>");
+MODULE_LICENSE("GPL");
+
+/**
+ * asix_soft_reset - software reset the PHY via BMCR_RESET bit
+ * @phydev: target phy_device struct
+ *
+ * Description: Perform a software PHY reset using the standard
+ * BMCR_RESET bit and poll for the reset bit to be cleared.
+ * Toggle BMCR_RESET bit off to accommodate broken AX8796B PHY implementation
+ * such as used on the Individual Computers' X-Surf 100 Zorro card.
+ *
+ * Returns: 0 on success, < 0 on failure
+ */
+static int asix_soft_reset(struct phy_device *phydev)
+{
+       int ret;
+
+       /* Asix PHY won't reset unless reset bit toggles */
+       ret = phy_write(phydev, MII_BMCR, 0);
+       if (ret < 0)
+               return ret;
+
+       return genphy_soft_reset(phydev);
+}
+
+static struct phy_driver asix_driver[] = { {
+       .phy_id         = PHY_ID_ASIX_AX88796B,
+       .name           = "Asix Electronics AX88796B",
+       .phy_id_mask    = 0xfffffff0,
+       /* PHY_BASIC_FEATURES */
+       .soft_reset     = asix_soft_reset,
+} };
+
+module_phy_driver(asix_driver);
+
+static struct mdio_device_id __maybe_unused asix_tbl[] = {
+       { PHY_ID_ASIX_AX88796B, 0xfffffff0 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(mdio, asix_tbl);
index 9044b95..4c0616b 100644 (file)
@@ -1073,6 +1073,7 @@ EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get);
 int phylink_ethtool_ksettings_set(struct phylink *pl,
                                  const struct ethtool_link_ksettings *kset)
 {
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(support);
        struct ethtool_link_ksettings our_kset;
        struct phylink_link_state config;
        int ret;
@@ -1083,11 +1084,12 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
            kset->base.autoneg != AUTONEG_ENABLE)
                return -EINVAL;
 
+       linkmode_copy(support, pl->supported);
        config = pl->link_config;
 
        /* Mask out unsupported advertisements */
        linkmode_and(config.advertising, kset->link_modes.advertising,
-                    pl->supported);
+                    support);
 
        /* FIXME: should we reject autoneg if phy/mac does not support it? */
        if (kset->base.autoneg == AUTONEG_DISABLE) {
@@ -1097,7 +1099,7 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
                 * duplex.
                 */
                s = phy_lookup_setting(kset->base.speed, kset->base.duplex,
-                                      pl->supported, false);
+                                      support, false);
                if (!s)
                        return -EINVAL;
 
@@ -1126,7 +1128,7 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
                __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising);
        }
 
-       if (phylink_validate(pl, pl->supported, &config))
+       if (phylink_validate(pl, support, &config))
                return -EINVAL;
 
        /* If autonegotiation is enabled, we must have an advertisement */
@@ -1576,6 +1578,7 @@ static int phylink_sfp_module_insert(void *upstream,
 {
        struct phylink *pl = upstream;
        __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(support1);
        struct phylink_link_state config;
        phy_interface_t iface;
        int ret = 0;
@@ -1603,6 +1606,8 @@ static int phylink_sfp_module_insert(void *upstream,
                return ret;
        }
 
+       linkmode_copy(support1, support);
+
        iface = sfp_select_interface(pl->sfp_bus, id, config.advertising);
        if (iface == PHY_INTERFACE_MODE_NA) {
                netdev_err(pl->netdev,
@@ -1612,7 +1617,7 @@ static int phylink_sfp_module_insert(void *upstream,
        }
 
        config.interface = iface;
-       ret = phylink_validate(pl, support, &config);
+       ret = phylink_validate(pl, support1, &config);
        if (ret) {
                netdev_err(pl->netdev, "validation of %s/%s with support %*pb failed: %d\n",
                           phylink_an_mode_str(MLO_AN_INBAND),
index d4635c2..71812be 100644 (file)
@@ -281,6 +281,7 @@ static int sfp_i2c_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
 {
        struct i2c_msg msgs[2];
        u8 bus_addr = a2 ? 0x51 : 0x50;
+       size_t this_len;
        int ret;
 
        msgs[0].addr = bus_addr;
@@ -292,11 +293,26 @@ static int sfp_i2c_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
        msgs[1].len = len;
        msgs[1].buf = buf;
 
-       ret = i2c_transfer(sfp->i2c, msgs, ARRAY_SIZE(msgs));
-       if (ret < 0)
-               return ret;
+       while (len) {
+               this_len = len;
+               if (this_len > 16)
+                       this_len = 16;
 
-       return ret == ARRAY_SIZE(msgs) ? len : 0;
+               msgs[1].len = this_len;
+
+               ret = i2c_transfer(sfp->i2c, msgs, ARRAY_SIZE(msgs));
+               if (ret < 0)
+                       return ret;
+
+               if (ret != ARRAY_SIZE(msgs))
+                       break;
+
+               msgs[1].buf += this_len;
+               dev_addr += this_len;
+               len -= this_len;
+       }
+
+       return msgs[1].buf - (u8 *)buf;
 }
 
 static int sfp_i2c_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
index 5f52e40..33d7bc5 100644 (file)
@@ -2747,3 +2747,42 @@ void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t)
                          jiffies + msecs_to_jiffies(collect_interval));
        }
 }
+
+#define FSEQ_REG(x) { .addr = (x), .str = #x, }
+
+void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt)
+{
+       struct iwl_trans *trans = fwrt->trans;
+       unsigned long flags;
+       int i;
+       struct {
+               u32 addr;
+               const char *str;
+       } fseq_regs[] = {
+               FSEQ_REG(FSEQ_ERROR_CODE),
+               FSEQ_REG(FSEQ_TOP_INIT_VERSION),
+               FSEQ_REG(FSEQ_CNVIO_INIT_VERSION),
+               FSEQ_REG(FSEQ_OTP_VERSION),
+               FSEQ_REG(FSEQ_TOP_CONTENT_VERSION),
+               FSEQ_REG(FSEQ_ALIVE_TOKEN),
+               FSEQ_REG(FSEQ_CNVI_ID),
+               FSEQ_REG(FSEQ_CNVR_ID),
+               FSEQ_REG(CNVI_AUX_MISC_CHIP),
+               FSEQ_REG(CNVR_AUX_MISC_CHIP),
+               FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM),
+               FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR),
+       };
+
+       if (!iwl_trans_grab_nic_access(trans, &flags))
+               return;
+
+       IWL_ERR(fwrt, "Fseq Registers:\n");
+
+       for (i = 0; i < ARRAY_SIZE(fseq_regs); i++)
+               IWL_ERR(fwrt, "0x%08X | %s\n",
+                       iwl_read_prph_no_grab(trans, fseq_regs[i].addr),
+                       fseq_regs[i].str);
+
+       iwl_trans_release_nic_access(trans, &flags);
+}
+IWL_EXPORT_SYMBOL(iwl_fw_error_print_fseq_regs);
index 2a9e560..fd0ad22 100644 (file)
@@ -471,4 +471,6 @@ static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt)
 }
 
 void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t);
+
+void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt);
 #endif  /* __iwl_fw_dbg_h__ */
index 852d3cb..fba2422 100644 (file)
@@ -1597,7 +1597,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
        goto free;
 
  out_free_fw:
-       iwl_dealloc_ucode(drv);
        release_firmware(ucode_raw);
  out_unbind:
        complete(&drv->request_firmware_complete);
index 8e6a0c3..8d930bf 100644 (file)
@@ -395,7 +395,11 @@ enum {
        WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK       = 0x80000000,
 };
 
-#define AUX_MISC_REG                   0xA200B0
+#define CNVI_AUX_MISC_CHIP                             0xA200B0
+#define CNVR_AUX_MISC_CHIP                             0xA2B800
+#define CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM         0xA29890
+#define CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR     0xA29938
+
 enum {
        HW_STEP_LOCATION_BITS = 24,
 };
@@ -408,7 +412,12 @@ enum aux_misc_master1_en {
 #define AUX_MISC_MASTER1_SMPHR_STATUS  0xA20800
 #define RSA_ENABLE                     0xA24B08
 #define PREG_AUX_BUS_WPROT_0           0xA04CC0
-#define PREG_PRPH_WPROT_0              0xA04CE0
+
+/* device family 9000 WPROT register */
+#define PREG_PRPH_WPROT_9000           0xA04CE0
+/* device family 22000 WPROT register */
+#define PREG_PRPH_WPROT_22000          0xA04D00
+
 #define SB_CPU_1_STATUS                        0xA01E30
 #define SB_CPU_2_STATUS                        0xA01E34
 #define UMAG_SB_CPU_1_STATUS           0xA038C0
@@ -442,4 +451,13 @@ enum {
 
 #define UREG_DOORBELL_TO_ISR6          0xA05C04
 #define UREG_DOORBELL_TO_ISR6_NMI_BIT  BIT(0)
+
+#define FSEQ_ERROR_CODE                        0xA340C8
+#define FSEQ_TOP_INIT_VERSION          0xA34038
+#define FSEQ_CNVIO_INIT_VERSION                0xA3403C
+#define FSEQ_OTP_VERSION               0xA340FC
+#define FSEQ_TOP_CONTENT_VERSION       0xA340F4
+#define FSEQ_ALIVE_TOKEN               0xA340F0
+#define FSEQ_CNVI_ID                   0xA3408C
+#define FSEQ_CNVR_ID                   0xA34090
 #endif                         /* __iwl_prph_h__ */
index 60f5d33..e7e68fb 100644 (file)
@@ -1972,26 +1972,6 @@ out:
        }
 }
 
-static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm)
-{
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-       const struct fw_img *img = &mvm->fw->img[IWL_UCODE_WOWLAN];
-       u32 len = img->sec[IWL_UCODE_SECTION_DATA].len;
-       u32 offs = img->sec[IWL_UCODE_SECTION_DATA].offset;
-
-       if (!mvm->store_d3_resume_sram)
-               return;
-
-       if (!mvm->d3_resume_sram) {
-               mvm->d3_resume_sram = kzalloc(len, GFP_KERNEL);
-               if (!mvm->d3_resume_sram)
-                       return;
-       }
-
-       iwl_trans_read_mem_bytes(mvm->trans, offs, mvm->d3_resume_sram, len);
-#endif
-}
-
 static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
                                       struct ieee80211_vif *vif)
 {
@@ -2054,8 +2034,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
        }
 
        iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);
-       /* query SRAM first in case we want event logging */
-       iwl_mvm_read_d3_sram(mvm);
 
        if (iwl_mvm_check_rt_status(mvm, vif)) {
                set_bit(STATUS_FW_ERROR, &mvm->trans->status);
index d4ff6b4..5b1bb76 100644 (file)
@@ -1557,59 +1557,6 @@ static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
 }
 #endif
 
-#ifdef CONFIG_PM_SLEEP
-static ssize_t iwl_dbgfs_d3_sram_write(struct iwl_mvm *mvm, char *buf,
-                                      size_t count, loff_t *ppos)
-{
-       int store;
-
-       if (sscanf(buf, "%d", &store) != 1)
-               return -EINVAL;
-
-       mvm->store_d3_resume_sram = store;
-
-       return count;
-}
-
-static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
-                                     size_t count, loff_t *ppos)
-{
-       struct iwl_mvm *mvm = file->private_data;
-       const struct fw_img *img;
-       int ofs, len, pos = 0;
-       size_t bufsz, ret;
-       char *buf;
-       u8 *ptr = mvm->d3_resume_sram;
-
-       img = &mvm->fw->img[IWL_UCODE_WOWLAN];
-       len = img->sec[IWL_UCODE_SECTION_DATA].len;
-
-       bufsz = len * 4 + 256;
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       pos += scnprintf(buf, bufsz, "D3 SRAM capture: %sabled\n",
-                        mvm->store_d3_resume_sram ? "en" : "dis");
-
-       if (ptr) {
-               for (ofs = 0; ofs < len; ofs += 16) {
-                       pos += scnprintf(buf + pos, bufsz - pos,
-                                        "0x%.4x %16ph\n", ofs, ptr + ofs);
-               }
-       } else {
-               pos += scnprintf(buf + pos, bufsz - pos,
-                                "(no data captured)\n");
-       }
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-
-       kfree(buf);
-
-       return ret;
-}
-#endif
-
 #define PRINT_MVM_REF(ref) do {                                                \
        if (mvm->refs[ref])                                             \
                pos += scnprintf(buf + pos, bufsz - pos,                \
@@ -1940,9 +1887,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
 #endif
 
-#ifdef CONFIG_PM_SLEEP
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
-#endif
 #ifdef CONFIG_ACPI
 MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
 #endif
@@ -2159,7 +2103,6 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
 #endif
 
 #ifdef CONFIG_PM_SLEEP
-       MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, 0600);
        MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400);
        debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir,
                            &mvm->d3_wake_sysassert);
index ab68b5d..1537175 100644 (file)
@@ -311,6 +311,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
        int ret;
        enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img;
        static const u16 alive_cmd[] = { MVM_ALIVE };
+       bool run_in_rfkill =
+               ucode_type == IWL_UCODE_INIT || iwl_mvm_has_unified_ucode(mvm);
 
        if (ucode_type == IWL_UCODE_REGULAR &&
            iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) &&
@@ -328,7 +330,12 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
                                   alive_cmd, ARRAY_SIZE(alive_cmd),
                                   iwl_alive_fn, &alive_data);
 
-       ret = iwl_trans_start_fw(mvm->trans, fw, ucode_type == IWL_UCODE_INIT);
+       /*
+        * We want to load the INIT firmware even in RFKILL
+        * For the unified firmware case, the ucode_type is not
+        * INIT, but we still need to run it.
+        */
+       ret = iwl_trans_start_fw(mvm->trans, fw, run_in_rfkill);
        if (ret) {
                iwl_fw_set_current_image(&mvm->fwrt, old_type);
                iwl_remove_notification(&mvm->notif_wait, &alive_wait);
@@ -433,7 +440,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
         * commands
         */
        ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(SYSTEM_GROUP,
-                                               INIT_EXTENDED_CFG_CMD), 0,
+                                               INIT_EXTENDED_CFG_CMD),
+                                  CMD_SEND_IN_RFKILL,
                                   sizeof(init_cfg), &init_cfg);
        if (ret) {
                IWL_ERR(mvm, "Failed to run init config command: %d\n",
@@ -457,7 +465,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
        }
 
        ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
-                                               NVM_ACCESS_COMPLETE), 0,
+                                               NVM_ACCESS_COMPLETE),
+                                  CMD_SEND_IN_RFKILL,
                                   sizeof(nvm_complete), &nvm_complete);
        if (ret) {
                IWL_ERR(mvm, "Failed to run complete NVM access: %d\n",
@@ -482,6 +491,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
                }
        }
 
+       mvm->rfkill_safe_init_done = true;
+
        return 0;
 
 error:
@@ -526,7 +537,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 
        lockdep_assert_held(&mvm->mutex);
 
-       if (WARN_ON_ONCE(mvm->calibrating))
+       if (WARN_ON_ONCE(mvm->rfkill_safe_init_done))
                return 0;
 
        iwl_init_notification_wait(&mvm->notif_wait,
@@ -576,7 +587,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
                goto remove_notif;
        }
 
-       mvm->calibrating = true;
+       mvm->rfkill_safe_init_done = true;
 
        /* Send TX valid antennas before triggering calibrations */
        ret = iwl_send_tx_ant_cfg(mvm, iwl_mvm_get_valid_tx_ant(mvm));
@@ -612,7 +623,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 remove_notif:
        iwl_remove_notification(&mvm->notif_wait, &calib_wait);
 out:
-       mvm->calibrating = false;
+       mvm->rfkill_safe_init_done = false;
        if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
                /* we want to debug INIT and we have no NVM - fake */
                mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
index 5c52469..fdbabca 100644 (file)
@@ -1209,7 +1209,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
 
        mvm->scan_status = 0;
        mvm->ps_disabled = false;
-       mvm->calibrating = false;
+       mvm->rfkill_safe_init_done = false;
 
        /* just in case one was running */
        iwl_mvm_cleanup_roc_te(mvm);
index 8dc2a98..02efcf2 100644 (file)
@@ -880,7 +880,7 @@ struct iwl_mvm {
        struct iwl_mvm_vif *bf_allowed_vif;
 
        bool hw_registered;
-       bool calibrating;
+       bool rfkill_safe_init_done;
        bool support_umac_log;
 
        u32 ampdu_ref;
@@ -1039,8 +1039,6 @@ struct iwl_mvm {
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        bool d3_wake_sysassert;
        bool d3_test_active;
-       bool store_d3_resume_sram;
-       void *d3_resume_sram;
        u32 d3_test_pme_ptr;
        struct ieee80211_vif *keep_vif;
        u32 last_netdetect_scans; /* no. of scans in the last net-detect wake */
index acd2fda..fad3bf5 100644 (file)
@@ -918,9 +918,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
        kfree(mvm->error_recovery_buf);
        mvm->error_recovery_buf = NULL;
 
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS)
-       kfree(mvm->d3_resume_sram);
-#endif
        iwl_trans_op_mode_leave(mvm->trans);
 
        iwl_phy_db_free(mvm->phy_db);
@@ -1212,7 +1209,8 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
 static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
 {
        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
-       bool calibrating = READ_ONCE(mvm->calibrating);
+       bool rfkill_safe_init_done = READ_ONCE(mvm->rfkill_safe_init_done);
+       bool unified = iwl_mvm_has_unified_ucode(mvm);
 
        if (state)
                set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
@@ -1221,15 +1219,23 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
 
        iwl_mvm_set_rfkill_state(mvm);
 
-       /* iwl_run_init_mvm_ucode is waiting for results, abort it */
-       if (calibrating)
+        /* iwl_run_init_mvm_ucode is waiting for results, abort it. */
+       if (rfkill_safe_init_done)
                iwl_abort_notification_waits(&mvm->notif_wait);
 
+       /*
+        * Don't ask the transport to stop the firmware. We'll do it
+        * after cfg80211 takes us down.
+        */
+       if (unified)
+               return false;
+
        /*
         * Stop the device if we run OPERATIONAL firmware or if we are in the
         * middle of the calibrations.
         */
-       return state && (mvm->fwrt.cur_fw_img != IWL_UCODE_INIT || calibrating);
+       return state && (mvm->fwrt.cur_fw_img != IWL_UCODE_INIT ||
+                        rfkill_safe_init_done);
 }
 
 static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
index 659e21b..be62f49 100644 (file)
@@ -441,7 +441,8 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
         */
        sta->max_amsdu_len = max_amsdu_len;
 
-       ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cfg_cmd), &cfg_cmd);
+       ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, sizeof(cfg_cmd),
+                                  &cfg_cmd);
        if (ret)
                IWL_ERR(mvm, "Failed to send rate scale config (%d)\n", ret);
 }
index b9914ef..cc56ab8 100644 (file)
@@ -596,6 +596,8 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
                iwl_mvm_dump_lmac_error_log(mvm, 1);
 
        iwl_mvm_dump_umac_error_log(mvm);
+
+       iwl_fw_error_print_fseq_regs(&mvm->fwrt);
 }
 
 int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id,
index b513037..85973dd 100644 (file)
@@ -928,7 +928,7 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
                                           MSIX_HW_INT_CAUSES_REG_RF_KILL);
        }
 
-       if (trans->cfg->device_family == IWL_DEVICE_FAMILY_9000) {
+       if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_9000) {
                /*
                 * On 9000-series devices this bit isn't enabled by default, so
                 * when we power down the device we need set the bit to allow it
index 803fcba..dfa1bed 100644 (file)
@@ -1698,26 +1698,26 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
        return 0;
 }
 
-static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
+static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       u32 hpm;
-       int err;
-
-       lockdep_assert_held(&trans_pcie->mutex);
+       u32 hpm, wprot;
 
-       err = iwl_pcie_prepare_card_hw(trans);
-       if (err) {
-               IWL_ERR(trans, "Error while preparing HW: %d\n", err);
-               return err;
+       switch (trans->cfg->device_family) {
+       case IWL_DEVICE_FAMILY_9000:
+               wprot = PREG_PRPH_WPROT_9000;
+               break;
+       case IWL_DEVICE_FAMILY_22000:
+               wprot = PREG_PRPH_WPROT_22000;
+               break;
+       default:
+               return 0;
        }
 
        hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG);
        if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) {
-               int wfpm_val = iwl_read_umac_prph_no_grab(trans,
-                                                         PREG_PRPH_WPROT_0);
+               u32 wprot_val = iwl_read_umac_prph_no_grab(trans, wprot);
 
-               if (wfpm_val & PREG_WFPM_ACCESS) {
+               if (wprot_val & PREG_WFPM_ACCESS) {
                        IWL_ERR(trans,
                                "Error, can not clear persistence bit\n");
                        return -EPERM;
@@ -1726,6 +1726,26 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
                                            hpm & ~PERSISTENCE_BIT);
        }
 
+       return 0;
+}
+
+static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       int err;
+
+       lockdep_assert_held(&trans_pcie->mutex);
+
+       err = iwl_pcie_prepare_card_hw(trans);
+       if (err) {
+               IWL_ERR(trans, "Error while preparing HW: %d\n", err);
+               return err;
+       }
+
+       err = iwl_trans_pcie_clear_persistence_bit(trans);
+       if (err)
+               return err;
+
        iwl_trans_pcie_sw_reset(trans);
 
        err = iwl_pcie_apm_init(trans);
@@ -3526,7 +3546,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                        hw_step |= ENABLE_WFPM;
                        iwl_write_umac_prph_no_grab(trans, WFPM_CTRL_REG,
                                                    hw_step);
-                       hw_step = iwl_read_prph_no_grab(trans, AUX_MISC_REG);
+                       hw_step = iwl_read_prph_no_grab(trans,
+                                                       CNVI_AUX_MISC_CHIP);
                        hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF;
                        if (hw_step == 0x3)
                                trans->hw_rev = (trans->hw_rev & 0xFFFFFFF3) |
@@ -3577,7 +3598,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                }
        } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
                   CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
-                  (trans->cfg != &iwl_ax200_cfg_cc ||
+                  ((trans->cfg != &iwl_ax200_cfg_cc &&
+                   trans->cfg != &killer1650x_2ax_cfg &&
+                   trans->cfg != &killer1650w_2ax_cfg) ||
                    trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) {
                u32 hw_status;
 
index 6845eb5..653d347 100644 (file)
@@ -329,6 +329,8 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
        struct ieee80211_vendor_ie *vendorhdr;
        u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
        int left_len, parsed_len = 0;
+       unsigned int token_len;
+       int err = 0;
 
        if (!info->tail || !info->tail_len)
                return 0;
@@ -344,6 +346,12 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
         */
        while (left_len > sizeof(struct ieee_types_header)) {
                hdr = (void *)(info->tail + parsed_len);
+               token_len = hdr->len + sizeof(struct ieee_types_header);
+               if (token_len > left_len) {
+                       err = -EINVAL;
+                       goto out;
+               }
+
                switch (hdr->element_id) {
                case WLAN_EID_SSID:
                case WLAN_EID_SUPP_RATES:
@@ -361,17 +369,20 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
                        if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
                                                    WLAN_OUI_TYPE_MICROSOFT_WMM,
                                                    (const u8 *)hdr,
-                                                   hdr->len + sizeof(struct ieee_types_header)))
+                                                   token_len))
                                break;
                        /* fall through */
                default:
-                       memcpy(gen_ie->ie_buffer + ie_len, hdr,
-                              hdr->len + sizeof(struct ieee_types_header));
-                       ie_len += hdr->len + sizeof(struct ieee_types_header);
+                       if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
+                               err = -EINVAL;
+                               goto out;
+                       }
+                       memcpy(gen_ie->ie_buffer + ie_len, hdr, token_len);
+                       ie_len += token_len;
                        break;
                }
-               left_len -= hdr->len + sizeof(struct ieee_types_header);
-               parsed_len += hdr->len + sizeof(struct ieee_types_header);
+               left_len -= token_len;
+               parsed_len += token_len;
        }
 
        /* parse only WPA vendor IE from tail, WMM IE is configured by
@@ -381,15 +392,17 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
                                                    WLAN_OUI_TYPE_MICROSOFT_WPA,
                                                    info->tail, info->tail_len);
        if (vendorhdr) {
-               memcpy(gen_ie->ie_buffer + ie_len, vendorhdr,
-                      vendorhdr->len + sizeof(struct ieee_types_header));
-               ie_len += vendorhdr->len + sizeof(struct ieee_types_header);
+               token_len = vendorhdr->len + sizeof(struct ieee_types_header);
+               if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
+                       err = -EINVAL;
+                       goto out;
+               }
+               memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, token_len);
+               ie_len += token_len;
        }
 
-       if (!ie_len) {
-               kfree(gen_ie);
-               return 0;
-       }
+       if (!ie_len)
+               goto out;
 
        gen_ie->ie_index = cpu_to_le16(gen_idx);
        gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
@@ -399,13 +412,15 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
 
        if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL,
                                         NULL, NULL)) {
-               kfree(gen_ie);
-               return -1;
+               err = -EINVAL;
+               goto out;
        }
 
        priv->gen_idx = gen_idx;
+
+ out:
        kfree(gen_ie);
-       return 0;
+       return err;
 }
 
 /* This function parses different IEs-head & tail IEs, beacon IEs,
index 935778e..c269a0d 100644 (file)
@@ -1247,6 +1247,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                }
                switch (element_id) {
                case WLAN_EID_SSID:
+                       if (element_len > IEEE80211_MAX_SSID_LEN)
+                               return -EINVAL;
                        bss_entry->ssid.ssid_len = element_len;
                        memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
                               element_len);
@@ -1256,6 +1258,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_SUPP_RATES:
+                       if (element_len > MWIFIEX_SUPPORTED_RATES)
+                               return -EINVAL;
                        memcpy(bss_entry->data_rates, current_ptr + 2,
                               element_len);
                        memcpy(bss_entry->supported_rates, current_ptr + 2,
@@ -1265,6 +1269,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_FH_PARAMS:
+                       if (element_len + 2 < sizeof(*fh_param_set))
+                               return -EINVAL;
                        fh_param_set =
                                (struct ieee_types_fh_param_set *) current_ptr;
                        memcpy(&bss_entry->phy_param_set.fh_param_set,
@@ -1273,6 +1279,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_DS_PARAMS:
+                       if (element_len + 2 < sizeof(*ds_param_set))
+                               return -EINVAL;
                        ds_param_set =
                                (struct ieee_types_ds_param_set *) current_ptr;
 
@@ -1284,6 +1292,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_CF_PARAMS:
+                       if (element_len + 2 < sizeof(*cf_param_set))
+                               return -EINVAL;
                        cf_param_set =
                                (struct ieee_types_cf_param_set *) current_ptr;
                        memcpy(&bss_entry->ss_param_set.cf_param_set,
@@ -1292,6 +1302,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_IBSS_PARAMS:
+                       if (element_len + 2 < sizeof(*ibss_param_set))
+                               return -EINVAL;
                        ibss_param_set =
                                (struct ieee_types_ibss_param_set *)
                                current_ptr;
@@ -1301,10 +1313,14 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_ERP_INFO:
+                       if (!element_len)
+                               return -EINVAL;
                        bss_entry->erp_flags = *(current_ptr + 2);
                        break;
 
                case WLAN_EID_PWR_CONSTRAINT:
+                       if (!element_len)
+                               return -EINVAL;
                        bss_entry->local_constraint = *(current_ptr + 2);
                        bss_entry->sensed_11h = true;
                        break;
@@ -1345,6 +1361,9 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_VENDOR_SPECIFIC:
+                       if (element_len + 2 < sizeof(vendor_ie->vend_hdr))
+                               return -EINVAL;
+
                        vendor_ie = (struct ieee_types_vendor_specific *)
                                        current_ptr;
 
index cf4265c..6284779 100644 (file)
@@ -8,7 +8,8 @@
 #include "reg.h"
 #include "debug.h"
 
-void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev, struct sk_buff *skb)
+static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,
+                                     struct sk_buff *skb)
 {
        struct rtw_c2h_cmd *c2h;
        u8 sub_cmd_id;
@@ -47,7 +48,8 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
        }
 }
 
-void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, u8 *h2c)
+static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
+                                   u8 *h2c)
 {
        u8 box;
        u8 box_state;
index f447361..b2dac46 100644 (file)
@@ -162,7 +162,8 @@ static void rtw_watch_dog_work(struct work_struct *work)
        rtwdev->stats.tx_cnt = 0;
        rtwdev->stats.rx_cnt = 0;
 
-       rtw_iterate_vifs(rtwdev, rtw_vif_watch_dog_iter, &data);
+       /* use atomic version to avoid taking local->iflist_mtx mutex */
+       rtw_iterate_vifs_atomic(rtwdev, rtw_vif_watch_dog_iter, &data);
 
        /* fw supports only one station associated to enter lps, if there are
         * more than two stations associated to the AP, then we can not enter
index 4381b36..404d894 100644 (file)
@@ -144,10 +144,10 @@ static void rtw_phy_stat_rssi_iter(void *data, struct ieee80211_sta *sta)
        struct rtw_phy_stat_iter_data *iter_data = data;
        struct rtw_dev *rtwdev = iter_data->rtwdev;
        struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
-       u8 rssi, rssi_level;
+       u8 rssi;
 
        rssi = ewma_rssi_read(&si->avg_rssi);
-       rssi_level = rtw_phy_get_rssi_level(si->rssi_level, rssi);
+       si->rssi_level = rtw_phy_get_rssi_level(si->rssi_level, rssi);
 
        rtw_fw_send_rssi_info(rtwdev, si);
 
@@ -423,6 +423,11 @@ static u64 rtw_phy_db_2_linear(u8 power_db)
        u8 i, j;
        u64 linear;
 
+       if (power_db > 96)
+               power_db = 96;
+       else if (power_db < 1)
+               return 1;
+
        /* 1dB ~ 96dB */
        i = (power_db - 1) >> 3;
        j = (power_db - 1) - (i << 3);
@@ -848,12 +853,13 @@ u8 rtw_vht_2s_rates[] = {
        DESC_RATEVHT2SS_MCS6, DESC_RATEVHT2SS_MCS7,
        DESC_RATEVHT2SS_MCS8, DESC_RATEVHT2SS_MCS9
 };
-u8 rtw_cck_size = ARRAY_SIZE(rtw_cck_rates);
-u8 rtw_ofdm_size = ARRAY_SIZE(rtw_ofdm_rates);
-u8 rtw_ht_1s_size = ARRAY_SIZE(rtw_ht_1s_rates);
-u8 rtw_ht_2s_size = ARRAY_SIZE(rtw_ht_2s_rates);
-u8 rtw_vht_1s_size = ARRAY_SIZE(rtw_vht_1s_rates);
-u8 rtw_vht_2s_size = ARRAY_SIZE(rtw_vht_2s_rates);
+
+static u8 rtw_cck_size = ARRAY_SIZE(rtw_cck_rates);
+static u8 rtw_ofdm_size = ARRAY_SIZE(rtw_ofdm_rates);
+static u8 rtw_ht_1s_size = ARRAY_SIZE(rtw_ht_1s_rates);
+static u8 rtw_ht_2s_size = ARRAY_SIZE(rtw_ht_2s_rates);
+static u8 rtw_vht_1s_size = ARRAY_SIZE(rtw_vht_1s_rates);
+static u8 rtw_vht_2s_size = ARRAY_SIZE(rtw_vht_2s_rates);
 u8 *rtw_rate_section[RTW_RATE_SECTION_MAX] = {
        rtw_cck_rates, rtw_ofdm_rates,
        rtw_ht_1s_rates, rtw_ht_2s_rates,
index f9c67ed..b42cd50 100644 (file)
@@ -929,11 +929,15 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
        u32 addr;
        u8 *data;
 
+       data = kzalloc(RSI_9116_REG_SIZE, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        status = rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR);
        if (status < 0) {
                rsi_dbg(ERR_ZONE,
                        "Unable to set ms word to common reg\n");
-               return status;
+               goto err;
        }
 
        rsi_dbg(INIT_ZONE, "%s: Bring TA out of reset\n", __func__);
@@ -944,7 +948,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
                                                  RSI_9116_REG_SIZE);
        if (status < 0) {
                rsi_dbg(ERR_ZONE, "Unable to hold TA threads\n");
-               return status;
+               goto err;
        }
 
        put_unaligned_le32(TA_SOFT_RST_CLR, data);
@@ -954,7 +958,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
                                                  RSI_9116_REG_SIZE);
        if (status < 0) {
                rsi_dbg(ERR_ZONE, "Unable to get TA out of reset\n");
-               return status;
+               goto err;
        }
 
        put_unaligned_le32(TA_PC_ZERO, data);
@@ -964,7 +968,8 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
                                                  RSI_9116_REG_SIZE);
        if (status < 0) {
                rsi_dbg(ERR_ZONE, "Unable to Reset TA PC value\n");
-               return -EINVAL;
+               status = -EINVAL;
+               goto err;
        }
 
        put_unaligned_le32(TA_RELEASE_THREAD_VALUE, data);
@@ -974,17 +979,19 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
                                                  RSI_9116_REG_SIZE);
        if (status < 0) {
                rsi_dbg(ERR_ZONE, "Unable to release TA threads\n");
-               return status;
+               goto err;
        }
 
        status = rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR);
        if (status < 0) {
                rsi_dbg(ERR_ZONE, "Unable to set ms word to common reg\n");
-               return status;
+               goto err;
        }
        rsi_dbg(INIT_ZONE, "***** TA Reset done *****\n");
 
-       return 0;
+err:
+       kfree(data);
+       return status;
 }
 
 static struct rsi_host_intf_ops sdio_host_intf_ops = {
index 121f760..217f15a 100644 (file)
@@ -562,14 +562,12 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
        /* We currently only support kernel addresses */
        BUG_ON(sid != KERNEL_SPACE);
 
-       mtsp(sid,1);
-
        /*
        ** WORD 1 - low order word
        ** "hints" parm includes the VALID bit!
        ** "dep" clobbers the physical address offset bits as well.
        */
-       pa = virt_to_phys(vba);
+       pa = lpa(vba);
        asm volatile("depw  %1,31,12,%0" : "+r" (pa) : "r" (hints));
        ((u32 *)pdir_ptr)[1] = (u32) pa;
 
@@ -594,7 +592,7 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
        ** Grab virtual index [0:11]
        ** Deposit virt_idx bits into I/O PDIR word
        */
-       asm volatile ("lci %%r0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
+       asm volatile ("lci %%r0(%1), %0" : "=r" (ci) : "r" (vba));
        asm volatile ("extru %1,19,12,%0" : "+r" (ci) : "r" (ci));
        asm volatile ("depw  %1,15,12,%0" : "+r" (pa) : "r" (ci));
 
index 8a9ea9b..296668c 100644 (file)
@@ -569,11 +569,10 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
        u64 pa; /* physical address */
        register unsigned ci; /* coherent index */
 
-       pa = virt_to_phys(vba);
+       pa = lpa(vba);
        pa &= IOVP_MASK;
 
-       mtsp(sid,1);
-       asm("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
+       asm("lci 0(%1), %0" : "=r" (ci) : "r" (vba));
        pa |= (ci >> PAGE_SHIFT) & 0xff;  /* move CI (8 bits) into lowest byte */
 
        pa |= SBA_PDIR_VALID_BIT;       /* set "valid" bit */
index 009f2c0..b1823d7 100644 (file)
@@ -1274,16 +1274,20 @@ static int qeth_setup_channel(struct qeth_channel *channel, bool alloc_buffers)
        return 0;
 }
 
-static void qeth_osa_set_output_queues(struct qeth_card *card, bool single)
+static int qeth_osa_set_output_queues(struct qeth_card *card, bool single)
 {
        unsigned int count = single ? 1 : card->dev->num_tx_queues;
+       int rc;
 
        rtnl_lock();
-       netif_set_real_num_tx_queues(card->dev, count);
+       rc = netif_set_real_num_tx_queues(card->dev, count);
        rtnl_unlock();
 
+       if (rc)
+               return rc;
+
        if (card->qdio.no_out_queues == count)
-               return;
+               return 0;
 
        if (atomic_read(&card->qdio.state) != QETH_QDIO_UNINITIALIZED)
                qeth_free_qdio_queues(card);
@@ -1293,12 +1297,14 @@ static void qeth_osa_set_output_queues(struct qeth_card *card, bool single)
 
        card->qdio.default_out_queue = single ? 0 : QETH_DEFAULT_QUEUE;
        card->qdio.no_out_queues = count;
+       return 0;
 }
 
 static int qeth_update_from_chp_desc(struct qeth_card *card)
 {
        struct ccw_device *ccwdev;
        struct channel_path_desc_fmt0 *chp_dsc;
+       int rc = 0;
 
        QETH_DBF_TEXT(SETUP, 2, "chp_desc");
 
@@ -1311,12 +1317,12 @@ static int qeth_update_from_chp_desc(struct qeth_card *card)
 
        if (IS_OSD(card) || IS_OSX(card))
                /* CHPP field bit 6 == 1 -> single queue */
-               qeth_osa_set_output_queues(card, chp_dsc->chpp & 0x02);
+               rc = qeth_osa_set_output_queues(card, chp_dsc->chpp & 0x02);
 
        kfree(chp_dsc);
        QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues);
        QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level);
-       return 0;
+       return rc;
 }
 
 static void qeth_init_qdio_info(struct qeth_card *card)
@@ -5597,8 +5603,12 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card)
                dev->hw_features |= NETIF_F_SG;
                dev->vlan_features |= NETIF_F_SG;
                if (IS_IQD(card)) {
-                       netif_set_real_num_tx_queues(dev, QETH_IQD_MIN_TXQ);
                        dev->features |= NETIF_F_SG;
+                       if (netif_set_real_num_tx_queues(dev,
+                                                        QETH_IQD_MIN_TXQ)) {
+                               free_netdev(dev);
+                               return NULL;
+                       }
                }
        }
 
index 2188012..ff8a6cd 100644 (file)
@@ -1680,7 +1680,7 @@ static void qeth_bridgeport_an_set_cb(void *priv,
 
        l2entry = (struct qdio_brinfo_entry_l2 *)entry;
        code = IPA_ADDR_CHANGE_CODE_MACADDR;
-       if (l2entry->addr_lnid.lnid)
+       if (l2entry->addr_lnid.lnid < VLAN_N_VID)
                code |= IPA_ADDR_CHANGE_CODE_VLANID;
        qeth_bridge_emit_host_event(card, anev_reg_unreg, code,
                (struct net_if_token *)&l2entry->nit,
index 0271833..13bf3e2 100644 (file)
@@ -1888,13 +1888,20 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
 static int qeth_l3_get_cast_type(struct sk_buff *skb)
 {
+       int ipv = qeth_get_ip_version(skb);
        struct neighbour *n = NULL;
        struct dst_entry *dst;
 
        rcu_read_lock();
        dst = skb_dst(skb);
-       if (dst)
-               n = dst_neigh_lookup_skb(dst, skb);
+       if (dst) {
+               struct rt6_info *rt = (struct rt6_info *) dst;
+
+               dst = dst_check(dst, (ipv == 6) ? rt6_get_cookie(rt) : 0);
+               if (dst)
+                       n = dst_neigh_lookup_skb(dst, skb);
+       }
+
        if (n) {
                int cast_type = n->type;
 
@@ -1909,8 +1916,10 @@ static int qeth_l3_get_cast_type(struct sk_buff *skb)
        rcu_read_unlock();
 
        /* no neighbour (eg AF_PACKET), fall back to target's IP address ... */
-       switch (qeth_get_ip_version(skb)) {
+       switch (ipv) {
        case 4:
+               if (ipv4_is_lbcast(ip_hdr(skb)->daddr))
+                       return RTN_BROADCAST;
                return ipv4_is_multicast(ip_hdr(skb)->daddr) ?
                                RTN_MULTICAST : RTN_UNICAST;
        case 6:
@@ -1940,6 +1949,7 @@ static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue,
        struct qeth_hdr_layer3 *l3_hdr = &hdr->hdr.l3;
        struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
        struct qeth_card *card = queue->card;
+       struct dst_entry *dst;
 
        hdr->hdr.l3.length = data_len;
 
@@ -1985,15 +1995,27 @@ static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue,
        }
 
        rcu_read_lock();
+       dst = skb_dst(skb);
+
        if (ipv == 4) {
-               struct rtable *rt = skb_rtable(skb);
+               struct rtable *rt;
+
+               if (dst)
+                       dst = dst_check(dst, 0);
+               rt = (struct rtable *) dst;
 
                *((__be32 *) &hdr->hdr.l3.next_hop.ipv4.addr) = (rt) ?
                                rt_nexthop(rt, ip_hdr(skb)->daddr) :
                                ip_hdr(skb)->daddr;
        } else {
                /* IPv6 */
-               const struct rt6_info *rt = skb_rt6_info(skb);
+               struct rt6_info *rt;
+
+               if (dst) {
+                       rt = (struct rt6_info *) dst;
+                       dst = dst_check(dst, rt6_get_cookie(rt));
+               }
+               rt = (struct rt6_info *) dst;
 
                if (rt && !ipv6_addr_any(&rt->rt6i_gateway))
                        l3_hdr->next_hop.ipv6_addr = rt->rt6i_gateway;
index df51a35..2d9df78 100644 (file)
@@ -604,12 +604,6 @@ static size_t init_iov_iter(struct vhost_virtqueue *vq, struct iov_iter *iter,
        return iov_iter_count(iter);
 }
 
-static bool vhost_exceeds_weight(int pkts, int total_len)
-{
-       return total_len >= VHOST_NET_WEIGHT ||
-              pkts >= VHOST_NET_PKT_WEIGHT;
-}
-
 static int get_tx_bufs(struct vhost_net *net,
                       struct vhost_net_virtqueue *nvq,
                       struct msghdr *msg,
@@ -779,7 +773,7 @@ static void handle_tx_copy(struct vhost_net *net, struct socket *sock)
        int sent_pkts = 0;
        bool sock_can_batch = (sock->sk->sk_sndbuf == INT_MAX);
 
-       for (;;) {
+       do {
                bool busyloop_intr = false;
 
                if (nvq->done_idx == VHOST_NET_BATCH)
@@ -845,11 +839,7 @@ done:
                vq->heads[nvq->done_idx].id = cpu_to_vhost32(vq, head);
                vq->heads[nvq->done_idx].len = 0;
                ++nvq->done_idx;
-               if (vhost_exceeds_weight(++sent_pkts, total_len)) {
-                       vhost_poll_queue(&vq->poll);
-                       break;
-               }
-       }
+       } while (likely(!vhost_exceeds_weight(vq, ++sent_pkts, total_len)));
 
        vhost_tx_batch(net, nvq, sock, &msg);
 }
@@ -874,7 +864,7 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock)
        bool zcopy_used;
        int sent_pkts = 0;
 
-       for (;;) {
+       do {
                bool busyloop_intr;
 
                /* Release DMAs done buffers first */
@@ -951,11 +941,7 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock)
                else
                        vhost_zerocopy_signal_used(net, vq);
                vhost_net_tx_packet(net);
-               if (unlikely(vhost_exceeds_weight(++sent_pkts, total_len))) {
-                       vhost_poll_queue(&vq->poll);
-                       break;
-               }
-       }
+       } while (likely(!vhost_exceeds_weight(vq, ++sent_pkts, total_len)));
 }
 
 /* Expects to be always run from workqueue - which acts as
@@ -1153,8 +1139,11 @@ static void handle_rx(struct vhost_net *net)
                vq->log : NULL;
        mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF);
 
-       while ((sock_len = vhost_net_rx_peek_head_len(net, sock->sk,
-                                                     &busyloop_intr))) {
+       do {
+               sock_len = vhost_net_rx_peek_head_len(net, sock->sk,
+                                                     &busyloop_intr);
+               if (!sock_len)
+                       break;
                sock_len += sock_hlen;
                vhost_len = sock_len + vhost_hlen;
                headcount = get_rx_bufs(vq, vq->heads + nvq->done_idx,
@@ -1239,14 +1228,11 @@ static void handle_rx(struct vhost_net *net)
                        vhost_log_write(vq, vq_log, log, vhost_len,
                                        vq->iov, in);
                total_len += vhost_len;
-               if (unlikely(vhost_exceeds_weight(++recv_pkts, total_len))) {
-                       vhost_poll_queue(&vq->poll);
-                       goto out;
-               }
-       }
+       } while (likely(!vhost_exceeds_weight(vq, ++recv_pkts, total_len)));
+
        if (unlikely(busyloop_intr))
                vhost_poll_queue(&vq->poll);
-       else
+       else if (!sock_len)
                vhost_net_enable_vq(net, vq);
 out:
        vhost_net_signal_used(nvq);
@@ -1338,7 +1324,8 @@ static int vhost_net_open(struct inode *inode, struct file *f)
                vhost_net_buf_init(&n->vqs[i].rxq);
        }
        vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX,
-                      UIO_MAXIOV + VHOST_NET_BATCH);
+                      UIO_MAXIOV + VHOST_NET_BATCH,
+                      VHOST_NET_PKT_WEIGHT, VHOST_NET_WEIGHT);
 
        vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev);
        vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev);
index c090d17..a9caf1b 100644 (file)
 #define VHOST_SCSI_PREALLOC_UPAGES 2048
 #define VHOST_SCSI_PREALLOC_PROT_SGLS 2048
 
+/* Max number of requests before requeueing the job.
+ * Using this limit prevents one virtqueue from starving others with
+ * request.
+ */
+#define VHOST_SCSI_WEIGHT 256
+
 struct vhost_scsi_inflight {
        /* Wait for the flush operation to finish */
        struct completion comp;
@@ -912,7 +918,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
        struct iov_iter in_iter, prot_iter, data_iter;
        u64 tag;
        u32 exp_data_len, data_direction;
-       int ret, prot_bytes;
+       int ret, prot_bytes, c = 0;
        u16 lun;
        u8 task_attr;
        bool t10_pi = vhost_has_feature(vq, VIRTIO_SCSI_F_T10_PI);
@@ -932,7 +938,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 
        vhost_disable_notify(&vs->dev, vq);
 
-       for (;;) {
+       do {
                ret = vhost_scsi_get_desc(vs, vq, &vc);
                if (ret)
                        goto err;
@@ -1112,7 +1118,7 @@ err:
                        break;
                else if (ret == -EIO)
                        vhost_scsi_send_bad_target(vs, vq, vc.head, vc.out);
-       }
+       } while (likely(!vhost_exceeds_weight(vq, ++c, 0)));
 out:
        mutex_unlock(&vq->mutex);
 }
@@ -1171,7 +1177,7 @@ vhost_scsi_ctl_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
        } v_req;
        struct vhost_scsi_ctx vc;
        size_t typ_size;
-       int ret;
+       int ret, c = 0;
 
        mutex_lock(&vq->mutex);
        /*
@@ -1185,7 +1191,7 @@ vhost_scsi_ctl_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 
        vhost_disable_notify(&vs->dev, vq);
 
-       for (;;) {
+       do {
                ret = vhost_scsi_get_desc(vs, vq, &vc);
                if (ret)
                        goto err;
@@ -1264,7 +1270,7 @@ err:
                        break;
                else if (ret == -EIO)
                        vhost_scsi_send_bad_target(vs, vq, vc.head, vc.out);
-       }
+       } while (likely(!vhost_exceeds_weight(vq, ++c, 0)));
 out:
        mutex_unlock(&vq->mutex);
 }
@@ -1621,7 +1627,8 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
                vqs[i] = &vs->vqs[i].vq;
                vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick;
        }
-       vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV);
+       vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV,
+                      VHOST_SCSI_WEIGHT, 0);
 
        vhost_scsi_init_inflight(vs, NULL);
 
index 1e3ed41..3f3eac4 100644 (file)
@@ -413,8 +413,24 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev)
                vhost_vq_free_iovecs(dev->vqs[i]);
 }
 
+bool vhost_exceeds_weight(struct vhost_virtqueue *vq,
+                         int pkts, int total_len)
+{
+       struct vhost_dev *dev = vq->dev;
+
+       if ((dev->byte_weight && total_len >= dev->byte_weight) ||
+           pkts >= dev->weight) {
+               vhost_poll_queue(&vq->poll);
+               return true;
+       }
+
+       return false;
+}
+EXPORT_SYMBOL_GPL(vhost_exceeds_weight);
+
 void vhost_dev_init(struct vhost_dev *dev,
-                   struct vhost_virtqueue **vqs, int nvqs, int iov_limit)
+                   struct vhost_virtqueue **vqs, int nvqs,
+                   int iov_limit, int weight, int byte_weight)
 {
        struct vhost_virtqueue *vq;
        int i;
@@ -428,6 +444,8 @@ void vhost_dev_init(struct vhost_dev *dev,
        dev->mm = NULL;
        dev->worker = NULL;
        dev->iov_limit = iov_limit;
+       dev->weight = weight;
+       dev->byte_weight = byte_weight;
        init_llist_head(&dev->work_list);
        init_waitqueue_head(&dev->wait);
        INIT_LIST_HEAD(&dev->read_list);
index 9490e7d..27a78a9 100644 (file)
@@ -171,10 +171,13 @@ struct vhost_dev {
        struct list_head pending_list;
        wait_queue_head_t wait;
        int iov_limit;
+       int weight;
+       int byte_weight;
 };
 
+bool vhost_exceeds_weight(struct vhost_virtqueue *vq, int pkts, int total_len);
 void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs,
-                   int nvqs, int iov_limit);
+                   int nvqs, int iov_limit, int weight, int byte_weight);
 long vhost_dev_set_owner(struct vhost_dev *dev);
 bool vhost_dev_has_owner(struct vhost_dev *dev);
 long vhost_dev_check_owner(struct vhost_dev *);
index bb5fc0e..814bed7 100644 (file)
 #include "vhost.h"
 
 #define VHOST_VSOCK_DEFAULT_HOST_CID   2
+/* Max number of bytes transferred before requeueing the job.
+ * Using this limit prevents one virtqueue from starving others. */
+#define VHOST_VSOCK_WEIGHT 0x80000
+/* Max number of packets transferred before requeueing the job.
+ * Using this limit prevents one virtqueue from starving others with
+ * small pkts.
+ */
+#define VHOST_VSOCK_PKT_WEIGHT 256
 
 enum {
        VHOST_VSOCK_FEATURES = VHOST_FEATURES,
@@ -78,6 +86,7 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
                            struct vhost_virtqueue *vq)
 {
        struct vhost_virtqueue *tx_vq = &vsock->vqs[VSOCK_VQ_TX];
+       int pkts = 0, total_len = 0;
        bool added = false;
        bool restart_tx = false;
 
@@ -89,7 +98,7 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
        /* Avoid further vmexits, we're already processing the virtqueue */
        vhost_disable_notify(&vsock->dev, vq);
 
-       for (;;) {
+       do {
                struct virtio_vsock_pkt *pkt;
                struct iov_iter iov_iter;
                unsigned out, in;
@@ -174,8 +183,9 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
                 */
                virtio_transport_deliver_tap_pkt(pkt);
 
+               total_len += pkt->len;
                virtio_transport_free_pkt(pkt);
-       }
+       } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len)));
        if (added)
                vhost_signal(&vsock->dev, vq);
 
@@ -350,7 +360,7 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work)
        struct vhost_vsock *vsock = container_of(vq->dev, struct vhost_vsock,
                                                 dev);
        struct virtio_vsock_pkt *pkt;
-       int head;
+       int head, pkts = 0, total_len = 0;
        unsigned int out, in;
        bool added = false;
 
@@ -360,7 +370,7 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work)
                goto out;
 
        vhost_disable_notify(&vsock->dev, vq);
-       for (;;) {
+       do {
                u32 len;
 
                if (!vhost_vsock_more_replies(vsock)) {
@@ -401,9 +411,11 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work)
                else
                        virtio_transport_free_pkt(pkt);
 
-               vhost_add_used(vq, head, sizeof(pkt->hdr) + len);
+               len += sizeof(pkt->hdr);
+               vhost_add_used(vq, head, len);
+               total_len += len;
                added = true;
-       }
+       } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len)));
 
 no_more_replies:
        if (added)
@@ -531,7 +543,9 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
        vsock->vqs[VSOCK_VQ_TX].handle_kick = vhost_vsock_handle_tx_kick;
        vsock->vqs[VSOCK_VQ_RX].handle_kick = vhost_vsock_handle_rx_kick;
 
-       vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs), UIO_MAXIOV);
+       vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs),
+                      UIO_MAXIOV, VHOST_VSOCK_PKT_WEIGHT,
+                      VHOST_VSOCK_WEIGHT);
 
        file->private_data = vsock;
        spin_lock_init(&vsock->send_pkt_list_lock);
index 9aea44e..023fc3b 100644 (file)
@@ -63,12 +63,12 @@ config VIRTIO_INPUT
 
         If unsure, say M.
 
- config VIRTIO_MMIO
+config VIRTIO_MMIO
        tristate "Platform bus driver for memory mapped virtio devices"
        depends on HAS_IOMEM && HAS_DMA
-       select VIRTIO
-       ---help---
-        This drivers provides support for memory mapped virtio
+       select VIRTIO
+       ---help---
+        This drivers provides support for memory mapped virtio
         platform device driver.
 
         If unsure, say N.
index c76db75..804c6a7 100644 (file)
@@ -113,19 +113,6 @@ struct object_info {
        __u16           filetype;
 };
 
-/* RISC OS 12-bit filetype converts to ,xyz hex filename suffix */
-static inline int append_filetype_suffix(char *buf, __u16 filetype)
-{
-       if (filetype == 0xffff) /* no explicit 12-bit file type was set */
-               return 0;
-
-       *buf++ = ',';
-       *buf++ = hex_asc_lo(filetype >> 8);
-       *buf++ = hex_asc_lo(filetype >> 4);
-       *buf++ = hex_asc_lo(filetype >> 0);
-       return 4;
-}
-
 struct adfs_dir_ops {
        int     (*read)(struct super_block *sb, unsigned int id, unsigned int sz, struct adfs_dir *dir);
        int     (*setpos)(struct adfs_dir *dir, unsigned int fpos);
@@ -172,6 +159,7 @@ extern const struct dentry_operations adfs_dentry_operations;
 extern const struct adfs_dir_ops adfs_f_dir_ops;
 extern const struct adfs_dir_ops adfs_fplus_dir_ops;
 
+void adfs_object_fixup(struct adfs_dir *dir, struct object_info *obj);
 extern int adfs_dir_update(struct super_block *sb, struct object_info *obj,
                           int wait);
 
index e18eff8..fe39310 100644 (file)
  */
 static DEFINE_RWLOCK(adfs_dir_lock);
 
+void adfs_object_fixup(struct adfs_dir *dir, struct object_info *obj)
+{
+       unsigned int dots, i;
+
+       /*
+        * RISC OS allows the use of '/' in directory entry names, so we need
+        * to fix these up.  '/' is typically used for FAT compatibility to
+        * represent '.', so do the same conversion here.  In any case, '.'
+        * will never be in a RISC OS name since it is used as the pathname
+        * separator.  Handle the case where we may generate a '.' or '..'
+        * name, replacing the first character with '^' (the RISC OS "parent
+        * directory" character.)
+        */
+       for (i = dots = 0; i < obj->name_len; i++)
+               if (obj->name[i] == '/') {
+                       obj->name[i] = '.';
+                       dots++;
+               }
+
+       if (obj->name_len <= 2 && dots == obj->name_len)
+               obj->name[0] = '^';
+
+       obj->filetype = -1;
+
+       /*
+        * object is a file and is filetyped and timestamped?
+        * RISC OS 12-bit filetype is stored in load_address[19:8]
+        */
+       if ((0 == (obj->attr & ADFS_NDA_DIRECTORY)) &&
+           (0xfff00000 == (0xfff00000 & obj->loadaddr))) {
+               obj->filetype = (__u16) ((0x000fff00 & obj->loadaddr) >> 8);
+
+               /* optionally append the ,xyz hex filetype suffix */
+               if (ADFS_SB(dir->sb)->s_ftsuffix) {
+                       __u16 filetype = obj->filetype;
+
+                       obj->name[obj->name_len++] = ',';
+                       obj->name[obj->name_len++] = hex_asc_lo(filetype >> 8);
+                       obj->name[obj->name_len++] = hex_asc_lo(filetype >> 4);
+                       obj->name[obj->name_len++] = hex_asc_lo(filetype >> 0);
+               }
+       }
+}
+
 static int
 adfs_readdir(struct file *file, struct dir_context *ctx)
 {
@@ -100,37 +144,36 @@ out:
        return ret;
 }
 
-static int
-adfs_match(const struct qstr *name, struct object_info *obj)
+static unsigned char adfs_tolower(unsigned char c)
 {
-       int i;
-
-       if (name->len != obj->name_len)
-               return 0;
+       if (c >= 'A' && c <= 'Z')
+               c += 'a' - 'A';
+       return c;
+}
 
-       for (i = 0; i < name->len; i++) {
-               char c1, c2;
+static int __adfs_compare(const unsigned char *qstr, u32 qlen,
+                         const char *str, u32 len)
+{
+       u32 i;
 
-               c1 = name->name[i];
-               c2 = obj->name[i];
+       if (qlen != len)
+               return 1;
 
-               if (c1 >= 'A' && c1 <= 'Z')
-                       c1 += 'a' - 'A';
-               if (c2 >= 'A' && c2 <= 'Z')
-                       c2 += 'a' - 'A';
+       for (i = 0; i < qlen; i++)
+               if (adfs_tolower(qstr[i]) != adfs_tolower(str[i]))
+                       return 1;
 
-               if (c1 != c2)
-                       return 0;
-       }
-       return 1;
+       return 0;
 }
 
-static int
-adfs_dir_lookup_byname(struct inode *inode, const struct qstr *name, struct object_info *obj)
+static int adfs_dir_lookup_byname(struct inode *inode, const struct qstr *qstr,
+                                 struct object_info *obj)
 {
        struct super_block *sb = inode->i_sb;
        const struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir;
+       const unsigned char *name;
        struct adfs_dir dir;
+       u32 name_len;
        int ret;
 
        ret = ops->read(sb, inode->i_ino, inode->i_size, &dir);
@@ -153,8 +196,10 @@ adfs_dir_lookup_byname(struct inode *inode, const struct qstr *name, struct obje
                goto unlock_out;
 
        ret = -ENOENT;
+       name = qstr->name;
+       name_len = qstr->len;
        while (ops->getnext(&dir, obj) == 0) {
-               if (adfs_match(name, obj)) {
+               if (!__adfs_compare(name, name_len, obj->name, obj->name_len)) {
                        ret = 0;
                        break;
                }
@@ -179,30 +224,18 @@ const struct file_operations adfs_dir_operations = {
 static int
 adfs_hash(const struct dentry *parent, struct qstr *qstr)
 {
-       const unsigned int name_len = ADFS_SB(parent->d_sb)->s_namelen;
        const unsigned char *name;
        unsigned long hash;
-       int i;
+       u32 len;
 
-       if (qstr->len < name_len)
-               return 0;
+       if (qstr->len > ADFS_SB(parent->d_sb)->s_namelen)
+               return -ENAMETOOLONG;
 
-       /*
-        * Truncate the name in place, avoids
-        * having to define a compare function.
-        */
-       qstr->len = i = name_len;
+       len = qstr->len;
        name = qstr->name;
        hash = init_name_hash(parent);
-       while (i--) {
-               char c;
-
-               c = *name++;
-               if (c >= 'A' && c <= 'Z')
-                       c += 'a' - 'A';
-
-               hash = partial_name_hash(c, hash);
-       }
+       while (len--)
+               hash = partial_name_hash(adfs_tolower(*name++), hash);
        qstr->hash = end_name_hash(hash);
 
        return 0;
@@ -212,30 +245,10 @@ adfs_hash(const struct dentry *parent, struct qstr *qstr)
  * Compare two names, taking note of the name length
  * requirements of the underlying filesystem.
  */
-static int
-adfs_compare(const struct dentry *dentry,
-               unsigned int len, const char *str, const struct qstr *name)
+static int adfs_compare(const struct dentry *dentry, unsigned int len,
+                       const char *str, const struct qstr *qstr)
 {
-       int i;
-
-       if (len != name->len)
-               return 1;
-
-       for (i = 0; i < name->len; i++) {
-               char a, b;
-
-               a = str[i];
-               b = name->name[i];
-
-               if (a >= 'A' && a <= 'Z')
-                       a += 'a' - 'A';
-               if (b >= 'A' && b <= 'Z')
-                       b += 'a' - 'A';
-
-               if (a != b)
-                       return 1;
-       }
-       return 0;
+       return __adfs_compare(qstr->name, qstr->len, str, len);
 }
 
 const struct dentry_operations adfs_dentry_operations = {
index 382c9d7..693f69e 100644 (file)
@@ -47,21 +47,6 @@ static inline void adfs_writeval(unsigned char *p, int len, unsigned int val)
        }
 }
 
-static inline int adfs_readname(char *buf, char *ptr, int maxlen)
-{
-       char *old_buf = buf;
-
-       while ((unsigned char)*ptr >= ' ' && maxlen--) {
-               if (*ptr == '/')
-                       *buf++ = '.';
-               else
-                       *buf++ = *ptr;
-               ptr++;
-       }
-
-       return buf - old_buf;
-}
-
 #define ror13(v) ((v >> 13) | (v << 19))
 
 #define dir_u8(idx)                            \
@@ -216,29 +201,23 @@ static inline void
 adfs_dir2obj(struct adfs_dir *dir, struct object_info *obj,
        struct adfs_direntry *de)
 {
-       obj->name_len = adfs_readname(obj->name, de->dirobname, ADFS_F_NAME_LEN);
+       unsigned int name_len;
+
+       for (name_len = 0; name_len < ADFS_F_NAME_LEN; name_len++) {
+               if (de->dirobname[name_len] < ' ')
+                       break;
+
+               obj->name[name_len] = de->dirobname[name_len];
+       }
+
+       obj->name_len = name_len;
        obj->file_id  = adfs_readval(de->dirinddiscadd, 3);
        obj->loadaddr = adfs_readval(de->dirload, 4);
        obj->execaddr = adfs_readval(de->direxec, 4);
        obj->size     = adfs_readval(de->dirlen,  4);
        obj->attr     = de->newdiratts;
-       obj->filetype = -1;
 
-       /*
-        * object is a file and is filetyped and timestamped?
-        * RISC OS 12-bit filetype is stored in load_address[19:8]
-        */
-       if ((0 == (obj->attr & ADFS_NDA_DIRECTORY)) &&
-               (0xfff00000 == (0xfff00000 & obj->loadaddr))) {
-               obj->filetype = (__u16) ((0x000fff00 & obj->loadaddr) >> 8);
-
-               /* optionally append the ,xyz hex filetype suffix */
-               if (ADFS_SB(dir->sb)->s_ftsuffix)
-                       obj->name_len +=
-                               append_filetype_suffix(
-                                       &obj->name[obj->name_len],
-                                       obj->filetype);
-       }
+       adfs_object_fixup(dir, obj);
 }
 
 /*
index c92cfb6..97b9f28 100644 (file)
@@ -169,7 +169,7 @@ adfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj)
                (struct adfs_bigdirheader *) dir->bh_fplus[0]->b_data;
        struct adfs_bigdirentry bde;
        unsigned int offset;
-       int i, ret = -ENOENT;
+       int ret = -ENOENT;
 
        if (dir->pos >= le32_to_cpu(h->bigdirentries))
                goto out;
@@ -193,27 +193,7 @@ adfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj)
        offset += le32_to_cpu(bde.bigdirobnameptr);
 
        dir_memcpy(dir, offset, obj->name, obj->name_len);
-       for (i = 0; i < obj->name_len; i++)
-               if (obj->name[i] == '/')
-                       obj->name[i] = '.';
-
-       obj->filetype = -1;
-
-       /*
-        * object is a file and is filetyped and timestamped?
-        * RISC OS 12-bit filetype is stored in load_address[19:8]
-        */
-       if ((0 == (obj->attr & ADFS_NDA_DIRECTORY)) &&
-               (0xfff00000 == (0xfff00000 & obj->loadaddr))) {
-               obj->filetype = (__u16) ((0x000fff00 & obj->loadaddr) >> 8);
-
-               /* optionally append the ,xyz hex filetype suffix */
-               if (ADFS_SB(dir->sb)->s_ftsuffix)
-                       obj->name_len +=
-                               append_filetype_suffix(
-                                       &obj->name[obj->name_len],
-                                       obj->filetype);
-       }
+       adfs_object_fixup(dir, obj);
 
        dir->pos += 1;
        ret = 0;
index 3959f08..b8f9c83 100644 (file)
@@ -1377,10 +1377,17 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
                if (err && !nbytes)
                        break;
 
-               if (write)
+               if (write) {
+                       if (!capable(CAP_FSETID)) {
+                               struct fuse_write_in *inarg;
+
+                               inarg = &req->misc.write.in;
+                               inarg->write_flags |= FUSE_WRITE_KILL_PRIV;
+                       }
                        nres = fuse_send_write(req, io, pos, nbytes, owner);
-               else
+               } else {
                        nres = fuse_send_read(req, io, pos, nbytes, owner);
+               }
 
                if (!io->async)
                        fuse_release_user_pages(req, io->should_dirty);
@@ -3014,6 +3021,16 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
        return ret;
 }
 
+static int fuse_writeback_range(struct inode *inode, loff_t start, loff_t end)
+{
+       int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+
+       if (!err)
+               fuse_sync_writes(inode);
+
+       return err;
+}
+
 static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
                                loff_t length)
 {
@@ -3042,12 +3059,10 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
                inode_lock(inode);
                if (mode & FALLOC_FL_PUNCH_HOLE) {
                        loff_t endbyte = offset + length - 1;
-                       err = filemap_write_and_wait_range(inode->i_mapping,
-                                                          offset, endbyte);
+
+                       err = fuse_writeback_range(inode, offset, endbyte);
                        if (err)
                                goto out;
-
-                       fuse_sync_writes(inode);
                }
        }
 
@@ -3055,7 +3070,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
            offset + length > i_size_read(inode)) {
                err = inode_newsize_ok(inode, offset + length);
                if (err)
-                       return err;
+                       goto out;
        }
 
        if (!(mode & FALLOC_FL_KEEP_SIZE))
@@ -3103,6 +3118,7 @@ static ssize_t fuse_copy_file_range(struct file *file_in, loff_t pos_in,
 {
        struct fuse_file *ff_in = file_in->private_data;
        struct fuse_file *ff_out = file_out->private_data;
+       struct inode *inode_in = file_inode(file_in);
        struct inode *inode_out = file_inode(file_out);
        struct fuse_inode *fi_out = get_fuse_inode(inode_out);
        struct fuse_conn *fc = ff_in->fc;
@@ -3126,15 +3142,20 @@ static ssize_t fuse_copy_file_range(struct file *file_in, loff_t pos_in,
        if (fc->no_copy_file_range)
                return -EOPNOTSUPP;
 
+       if (fc->writeback_cache) {
+               inode_lock(inode_in);
+               err = fuse_writeback_range(inode_in, pos_in, pos_in + len);
+               inode_unlock(inode_in);
+               if (err)
+                       return err;
+       }
+
        inode_lock(inode_out);
 
        if (fc->writeback_cache) {
-               err = filemap_write_and_wait_range(inode_out->i_mapping,
-                                                  pos_out, pos_out + len);
+               err = fuse_writeback_range(inode_out, pos_out, pos_out + len);
                if (err)
                        goto out;
-
-               fuse_sync_writes(inode_out);
        }
 
        if (is_unstable)
index 15c605c..71c28ff 100644 (file)
@@ -140,7 +140,7 @@ void gfs2_glock_free(struct gfs2_glock *gl)
 {
        struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 
-       BUG_ON(test_bit(GLF_REVOKES, &gl->gl_flags));
+       BUG_ON(atomic_read(&gl->gl_revokes));
        rhashtable_remove_fast(&gl_hash_table, &gl->gl_node, ht_parms);
        smp_mb();
        wake_up_glock(gl);
@@ -1801,7 +1801,7 @@ void gfs2_dump_glock(struct seq_file *seq, struct gfs2_glock *gl)
                  state2str(gl->gl_target),
                  state2str(gl->gl_demote_state), dtime,
                  atomic_read(&gl->gl_ail_count),
-                 test_bit(GLF_REVOKES, &gl->gl_flags) ? 1 : 0,
+                 atomic_read(&gl->gl_revokes),
                  (int)gl->gl_lockref.count, gl->gl_hold_time);
 
        list_for_each_entry(gh, &gl->gl_holders, gh_list)
index b157550..1d35e0d 100644 (file)
@@ -345,7 +345,6 @@ enum {
        GLF_OBJECT                      = 14, /* Used only for tracing */
        GLF_BLOCKING                    = 15,
        GLF_INODE_CREATING              = 16, /* Inode creation occurring */
-       GLF_REVOKES                     = 17, /* Glock has revokes in queue */
 };
 
 struct gfs2_glock {
@@ -375,6 +374,7 @@ struct gfs2_glock {
        struct list_head gl_lru;
        struct list_head gl_ail_list;
        atomic_t gl_ail_count;
+       atomic_t gl_revokes;
        struct delayed_work gl_work;
        union {
                /* For inode and iopen glocks only */
index a2e1df4..86703c9 100644 (file)
@@ -606,10 +606,8 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        gfs2_remove_from_ail(bd); /* drops ref on bh */
        bd->bd_bh = NULL;
        sdp->sd_log_num_revoke++;
-       if (!test_bit(GLF_REVOKES, &gl->gl_flags)) {
-               set_bit(GLF_REVOKES, &gl->gl_flags);
+       if (atomic_inc_return(&gl->gl_revokes) == 1)
                gfs2_glock_hold(gl);
-       }
        set_bit(GLF_LFLUSH, &gl->gl_flags);
        list_add(&bd->bd_list, &sdp->sd_log_revokes);
 }
index 33ab662..bb0e5b8 100644 (file)
@@ -860,34 +860,19 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 {
        struct list_head *head = &sdp->sd_log_revokes;
-       struct gfs2_bufdata *bd, *tmp;
-
-       /*
-        * Glocks can be referenced repeatedly on the revoke list, but the list
-        * only holds one reference.  All glocks on the list will have the
-        * GLF_REVOKES flag set initially.
-        */
-
-       list_for_each_entry_safe(bd, tmp, head, bd_list) {
-               struct gfs2_glock *gl = bd->bd_gl;
+       struct gfs2_bufdata *bd;
+       struct gfs2_glock *gl;
 
-               if (test_bit(GLF_REVOKES, &gl->gl_flags)) {
-                       /* Keep each glock on the list exactly once. */
-                       clear_bit(GLF_REVOKES, &gl->gl_flags);
-                       continue;
+       while (!list_empty(head)) {
+               bd = list_entry(head->next, struct gfs2_bufdata, bd_list);
+               list_del_init(&bd->bd_list);
+               gl = bd->bd_gl;
+               if (atomic_dec_return(&gl->gl_revokes) == 0) {
+                       clear_bit(GLF_LFLUSH, &gl->gl_flags);
+                       gfs2_glock_queue_put(gl);
                }
-               list_del(&bd->bd_list);
-               kmem_cache_free(gfs2_bufdata_cachep, bd);
-       }
-       list_for_each_entry_safe(bd, tmp, head, bd_list) {
-               struct gfs2_glock *gl = bd->bd_gl;
-
-               list_del(&bd->bd_list);
                kmem_cache_free(gfs2_bufdata_cachep, bd);
-               clear_bit(GLF_LFLUSH, &gl->gl_flags);
-               gfs2_glock_queue_put(gl);
        }
-       /* the list is empty now */
 }
 
 static void revoke_lo_before_scan(struct gfs2_jdesc *jd,
index c700738..136484e 100644 (file)
@@ -59,6 +59,7 @@ static void gfs2_init_glock_once(void *foo)
        INIT_LIST_HEAD(&gl->gl_lru);
        INIT_LIST_HEAD(&gl->gl_ail_list);
        atomic_set(&gl->gl_ail_count, 0);
+       atomic_set(&gl->gl_revokes, 0);
 }
 
 static void gfs2_init_gl_aspace_once(void *foo)
index fbf6b1f..2aa4dd0 100644 (file)
@@ -1477,7 +1477,7 @@ static void gfs2_final_release_pages(struct gfs2_inode *ip)
        truncate_inode_pages(gfs2_glock2aspace(ip->i_gl), 0);
        truncate_inode_pages(&inode->i_data, 0);
 
-       if (!test_bit(GLF_REVOKES, &gl->gl_flags)) {
+       if (atomic_read(&gl->gl_revokes) == 0) {
                clear_bit(GLF_LFLUSH, &gl->gl_flags);
                clear_bit(GLF_DIRTY, &gl->gl_flags);
        }
index c29cbef..e38f4af 100644 (file)
@@ -6932,7 +6932,6 @@ struct nfs4_lock_waiter {
        struct task_struct      *task;
        struct inode            *inode;
        struct nfs_lowner       *owner;
-       bool                    notified;
 };
 
 static int
@@ -6954,13 +6953,13 @@ nfs4_wake_lock_waiter(wait_queue_entry_t *wait, unsigned int mode, int flags, vo
                /* Make sure it's for the right inode */
                if (nfs_compare_fh(NFS_FH(waiter->inode), &cbnl->cbnl_fh))
                        return 0;
-
-               waiter->notified = true;
        }
 
        /* override "private" so we can use default_wake_function */
        wait->private = waiter->task;
-       ret = autoremove_wake_function(wait, mode, flags, key);
+       ret = woken_wake_function(wait, mode, flags, key);
+       if (ret)
+               list_del_init(&wait->entry);
        wait->private = waiter;
        return ret;
 }
@@ -6969,7 +6968,6 @@ static int
 nfs4_retry_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
        int status = -ERESTARTSYS;
-       unsigned long flags;
        struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner;
        struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs_client *clp = server->nfs_client;
@@ -6979,8 +6977,7 @@ nfs4_retry_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
                                    .s_dev = server->s_dev };
        struct nfs4_lock_waiter waiter = { .task  = current,
                                           .inode = state->inode,
-                                          .owner = &owner,
-                                          .notified = false };
+                                          .owner = &owner};
        wait_queue_entry_t wait;
 
        /* Don't bother with waitqueue if we don't expect a callback */
@@ -6990,27 +6987,22 @@ nfs4_retry_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
        init_wait(&wait);
        wait.private = &waiter;
        wait.func = nfs4_wake_lock_waiter;
-       add_wait_queue(q, &wait);
 
        while(!signalled()) {
-               waiter.notified = false;
+               add_wait_queue(q, &wait);
                status = nfs4_proc_setlk(state, cmd, request);
-               if ((status != -EAGAIN) || IS_SETLK(cmd))
+               if ((status != -EAGAIN) || IS_SETLK(cmd)) {
+                       finish_wait(q, &wait);
                        break;
-
-               status = -ERESTARTSYS;
-               spin_lock_irqsave(&q->lock, flags);
-               if (waiter.notified) {
-                       spin_unlock_irqrestore(&q->lock, flags);
-                       continue;
                }
-               set_current_state(TASK_INTERRUPTIBLE);
-               spin_unlock_irqrestore(&q->lock, flags);
 
-               freezable_schedule_timeout(NFS4_LOCK_MAXTIMEOUT);
+               status = -ERESTARTSYS;
+               freezer_do_not_count();
+               wait_woken(&wait, TASK_INTERRUPTIBLE, NFS4_LOCK_MAXTIMEOUT);
+               freezer_count();
+               finish_wait(q, &wait);
        }
 
-       finish_wait(q, &wait);
        return status;
 }
 #else /* !CONFIG_NFS_V4_1 */
index 540a8b8..340a6ad 100644 (file)
@@ -426,7 +426,8 @@ static unsigned int ovl_get_inode_flags(struct inode *inode)
        return ovl_iflags;
 }
 
-static long ovl_ioctl_set_flags(struct file *file, unsigned long arg)
+static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd,
+                               unsigned long arg)
 {
        long ret;
        struct inode *inode = file_inode(file);
@@ -456,7 +457,7 @@ static long ovl_ioctl_set_flags(struct file *file, unsigned long arg)
        if (ret)
                goto unlock;
 
-       ret = ovl_real_ioctl(file, FS_IOC_SETFLAGS, arg);
+       ret = ovl_real_ioctl(file, cmd, arg);
 
        ovl_copyflags(ovl_inode_real(inode), inode);
 unlock:
@@ -474,11 +475,13 @@ static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
        switch (cmd) {
        case FS_IOC_GETFLAGS:
+       case FS_IOC_FSGETXATTR:
                ret = ovl_real_ioctl(file, cmd, arg);
                break;
 
        case FS_IOC_SETFLAGS:
-               ret = ovl_ioctl_set_flags(file, arg);
+       case FS_IOC_FSSETXATTR:
+               ret = ovl_ioctl_set_flags(file, cmd, arg);
                break;
 
        default:
index b48273e..f7eba21 100644 (file)
@@ -777,6 +777,54 @@ struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real,
        return inode;
 }
 
+bool ovl_lookup_trap_inode(struct super_block *sb, struct dentry *dir)
+{
+       struct inode *key = d_inode(dir);
+       struct inode *trap;
+       bool res;
+
+       trap = ilookup5(sb, (unsigned long) key, ovl_inode_test, key);
+       if (!trap)
+               return false;
+
+       res = IS_DEADDIR(trap) && !ovl_inode_upper(trap) &&
+                                 !ovl_inode_lower(trap);
+
+       iput(trap);
+       return res;
+}
+
+/*
+ * Create an inode cache entry for layer root dir, that will intentionally
+ * fail ovl_verify_inode(), so any lookup that will find some layer root
+ * will fail.
+ */
+struct inode *ovl_get_trap_inode(struct super_block *sb, struct dentry *dir)
+{
+       struct inode *key = d_inode(dir);
+       struct inode *trap;
+
+       if (!d_is_dir(dir))
+               return ERR_PTR(-ENOTDIR);
+
+       trap = iget5_locked(sb, (unsigned long) key, ovl_inode_test,
+                           ovl_inode_set, key);
+       if (!trap)
+               return ERR_PTR(-ENOMEM);
+
+       if (!(trap->i_state & I_NEW)) {
+               /* Conflicting layer roots? */
+               iput(trap);
+               return ERR_PTR(-ELOOP);
+       }
+
+       trap->i_mode = S_IFDIR;
+       trap->i_flags = S_DEAD;
+       unlock_new_inode(trap);
+
+       return trap;
+}
+
 /*
  * Does overlay inode need to be hashed by lower inode?
  */
index efd3723..badf039 100644 (file)
@@ -18,6 +18,7 @@
 #include "overlayfs.h"
 
 struct ovl_lookup_data {
+       struct super_block *sb;
        struct qstr name;
        bool is_dir;
        bool opaque;
@@ -244,6 +245,12 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
                if (!d->metacopy || d->last)
                        goto out;
        } else {
+               if (ovl_lookup_trap_inode(d->sb, this)) {
+                       /* Caught in a trap of overlapping layers */
+                       err = -ELOOP;
+                       goto out_err;
+               }
+
                if (last_element)
                        d->is_dir = true;
                if (d->last)
@@ -819,6 +826,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
        int err;
        bool metacopy = false;
        struct ovl_lookup_data d = {
+               .sb = dentry->d_sb,
                .name = dentry->d_name,
                .is_dir = false,
                .opaque = false,
index d26efed..cec4007 100644 (file)
@@ -270,6 +270,7 @@ void ovl_clear_flag(unsigned long flag, struct inode *inode);
 bool ovl_test_flag(unsigned long flag, struct inode *inode);
 bool ovl_inuse_trylock(struct dentry *dentry);
 void ovl_inuse_unlock(struct dentry *dentry);
+bool ovl_is_inuse(struct dentry *dentry);
 bool ovl_need_index(struct dentry *dentry);
 int ovl_nlink_start(struct dentry *dentry);
 void ovl_nlink_end(struct dentry *dentry);
@@ -376,6 +377,8 @@ struct ovl_inode_params {
 struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev);
 struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real,
                               bool is_upper);
+bool ovl_lookup_trap_inode(struct super_block *sb, struct dentry *dir);
+struct inode *ovl_get_trap_inode(struct super_block *sb, struct dentry *dir);
 struct inode *ovl_get_inode(struct super_block *sb,
                            struct ovl_inode_params *oip);
 static inline void ovl_copyattr(struct inode *from, struct inode *to)
index ec23703..6ed1ace 100644 (file)
@@ -29,6 +29,8 @@ struct ovl_sb {
 
 struct ovl_layer {
        struct vfsmount *mnt;
+       /* Trap in ovl inode cache */
+       struct inode *trap;
        struct ovl_sb *fs;
        /* Index of this layer in fs root (upper idx == 0) */
        int idx;
@@ -65,6 +67,10 @@ struct ovl_fs {
        /* Did we take the inuse lock? */
        bool upperdir_locked;
        bool workdir_locked;
+       /* Traps in ovl inode cache */
+       struct inode *upperdir_trap;
+       struct inode *workdir_trap;
+       struct inode *indexdir_trap;
        /* Inode numbers in all layers do not use the high xino_bits */
        unsigned int xino_bits;
 };
index 5ec4fc2..746ea36 100644 (file)
@@ -215,6 +215,9 @@ static void ovl_free_fs(struct ovl_fs *ofs)
 {
        unsigned i;
 
+       iput(ofs->indexdir_trap);
+       iput(ofs->workdir_trap);
+       iput(ofs->upperdir_trap);
        dput(ofs->indexdir);
        dput(ofs->workdir);
        if (ofs->workdir_locked)
@@ -223,8 +226,10 @@ static void ovl_free_fs(struct ovl_fs *ofs)
        if (ofs->upperdir_locked)
                ovl_inuse_unlock(ofs->upper_mnt->mnt_root);
        mntput(ofs->upper_mnt);
-       for (i = 0; i < ofs->numlower; i++)
+       for (i = 0; i < ofs->numlower; i++) {
+               iput(ofs->lower_layers[i].trap);
                mntput(ofs->lower_layers[i].mnt);
+       }
        for (i = 0; i < ofs->numlowerfs; i++)
                free_anon_bdev(ofs->lower_fs[i].pseudo_dev);
        kfree(ofs->lower_layers);
@@ -983,7 +988,26 @@ static const struct xattr_handler *ovl_xattr_handlers[] = {
        NULL
 };
 
-static int ovl_get_upper(struct ovl_fs *ofs, struct path *upperpath)
+static int ovl_setup_trap(struct super_block *sb, struct dentry *dir,
+                         struct inode **ptrap, const char *name)
+{
+       struct inode *trap;
+       int err;
+
+       trap = ovl_get_trap_inode(sb, dir);
+       err = PTR_ERR(trap);
+       if (IS_ERR(trap)) {
+               if (err == -ELOOP)
+                       pr_err("overlayfs: conflicting %s path\n", name);
+               return err;
+       }
+
+       *ptrap = trap;
+       return 0;
+}
+
+static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs,
+                        struct path *upperpath)
 {
        struct vfsmount *upper_mnt;
        int err;
@@ -1003,6 +1027,11 @@ static int ovl_get_upper(struct ovl_fs *ofs, struct path *upperpath)
        if (err)
                goto out;
 
+       err = ovl_setup_trap(sb, upperpath->dentry, &ofs->upperdir_trap,
+                            "upperdir");
+       if (err)
+               goto out;
+
        upper_mnt = clone_private_mount(upperpath);
        err = PTR_ERR(upper_mnt);
        if (IS_ERR(upper_mnt)) {
@@ -1029,7 +1058,8 @@ out:
        return err;
 }
 
-static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath)
+static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
+                           struct path *workpath)
 {
        struct vfsmount *mnt = ofs->upper_mnt;
        struct dentry *temp;
@@ -1044,6 +1074,10 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath)
        if (!ofs->workdir)
                goto out;
 
+       err = ovl_setup_trap(sb, ofs->workdir, &ofs->workdir_trap, "workdir");
+       if (err)
+               goto out;
+
        /*
         * Upper should support d_type, else whiteouts are visible.  Given
         * workdir and upper are on same fs, we can do iterate_dir() on
@@ -1104,7 +1138,8 @@ out:
        return err;
 }
 
-static int ovl_get_workdir(struct ovl_fs *ofs, struct path *upperpath)
+static int ovl_get_workdir(struct super_block *sb, struct ovl_fs *ofs,
+                          struct path *upperpath)
 {
        int err;
        struct path workpath = { };
@@ -1135,19 +1170,16 @@ static int ovl_get_workdir(struct ovl_fs *ofs, struct path *upperpath)
                pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n");
        }
 
-       err = ovl_make_workdir(ofs, &workpath);
-       if (err)
-               goto out;
+       err = ovl_make_workdir(sb, ofs, &workpath);
 
-       err = 0;
 out:
        path_put(&workpath);
 
        return err;
 }
 
-static int ovl_get_indexdir(struct ovl_fs *ofs, struct ovl_entry *oe,
-                           struct path *upperpath)
+static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs,
+                           struct ovl_entry *oe, struct path *upperpath)
 {
        struct vfsmount *mnt = ofs->upper_mnt;
        int err;
@@ -1166,6 +1198,11 @@ static int ovl_get_indexdir(struct ovl_fs *ofs, struct ovl_entry *oe,
 
        ofs->indexdir = ovl_workdir_create(ofs, OVL_INDEXDIR_NAME, true);
        if (ofs->indexdir) {
+               err = ovl_setup_trap(sb, ofs->indexdir, &ofs->indexdir_trap,
+                                    "indexdir");
+               if (err)
+                       goto out;
+
                /*
                 * Verify upper root is exclusively associated with index dir.
                 * Older kernels stored upper fh in "trusted.overlay.origin"
@@ -1253,8 +1290,8 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
        return ofs->numlowerfs;
 }
 
-static int ovl_get_lower_layers(struct ovl_fs *ofs, struct path *stack,
-                               unsigned int numlower)
+static int ovl_get_lower_layers(struct super_block *sb, struct ovl_fs *ofs,
+                               struct path *stack, unsigned int numlower)
 {
        int err;
        unsigned int i;
@@ -1272,16 +1309,28 @@ static int ovl_get_lower_layers(struct ovl_fs *ofs, struct path *stack,
 
        for (i = 0; i < numlower; i++) {
                struct vfsmount *mnt;
+               struct inode *trap;
                int fsid;
 
                err = fsid = ovl_get_fsid(ofs, &stack[i]);
                if (err < 0)
                        goto out;
 
+               err = -EBUSY;
+               if (ovl_is_inuse(stack[i].dentry)) {
+                       pr_err("overlayfs: lowerdir is in-use as upperdir/workdir\n");
+                       goto out;
+               }
+
+               err = ovl_setup_trap(sb, stack[i].dentry, &trap, "lowerdir");
+               if (err)
+                       goto out;
+
                mnt = clone_private_mount(&stack[i]);
                err = PTR_ERR(mnt);
                if (IS_ERR(mnt)) {
                        pr_err("overlayfs: failed to clone lowerpath\n");
+                       iput(trap);
                        goto out;
                }
 
@@ -1291,6 +1340,7 @@ static int ovl_get_lower_layers(struct ovl_fs *ofs, struct path *stack,
                 */
                mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME;
 
+               ofs->lower_layers[ofs->numlower].trap = trap;
                ofs->lower_layers[ofs->numlower].mnt = mnt;
                ofs->lower_layers[ofs->numlower].idx = i + 1;
                ofs->lower_layers[ofs->numlower].fsid = fsid;
@@ -1385,7 +1435,7 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
                goto out_err;
        }
 
-       err = ovl_get_lower_layers(ofs, stack, numlower);
+       err = ovl_get_lower_layers(sb, ofs, stack, numlower);
        if (err)
                goto out_err;
 
@@ -1417,6 +1467,85 @@ out_err:
        goto out;
 }
 
+/*
+ * Check if this layer root is a descendant of:
+ * - another layer of this overlayfs instance
+ * - upper/work dir of any overlayfs instance
+ * - a disconnected dentry (detached root)
+ */
+static int ovl_check_layer(struct super_block *sb, struct dentry *dentry,
+                          const char *name)
+{
+       struct dentry *next, *parent;
+       bool is_root = false;
+       int err = 0;
+
+       if (!dentry || dentry == dentry->d_sb->s_root)
+               return 0;
+
+       next = dget(dentry);
+       /* Walk back ancestors to fs root (inclusive) looking for traps */
+       do {
+               parent = dget_parent(next);
+               is_root = (parent == next);
+               if (ovl_is_inuse(parent)) {
+                       err = -EBUSY;
+                       pr_err("overlayfs: %s path overlapping in-use upperdir/workdir\n",
+                              name);
+               } else if (ovl_lookup_trap_inode(sb, parent)) {
+                       err = -ELOOP;
+                       pr_err("overlayfs: overlapping %s path\n", name);
+               }
+               dput(next);
+               next = parent;
+       } while (!err && !is_root);
+
+       /* Did we really walk to fs root or found a detached root? */
+       if (!err && next != dentry->d_sb->s_root) {
+               err = -ESTALE;
+               pr_err("overlayfs: disconnected %s path\n", name);
+       }
+
+       dput(next);
+
+       return err;
+}
+
+/*
+ * Check if any of the layers or work dirs overlap.
+ */
+static int ovl_check_overlapping_layers(struct super_block *sb,
+                                       struct ovl_fs *ofs)
+{
+       int i, err;
+
+       if (ofs->upper_mnt) {
+               err = ovl_check_layer(sb, ofs->upper_mnt->mnt_root, "upperdir");
+               if (err)
+                       return err;
+
+               /*
+                * Checking workbasedir avoids hitting ovl_is_inuse(parent) of
+                * this instance and covers overlapping work and index dirs,
+                * unless work or index dir have been moved since created inside
+                * workbasedir.  In that case, we already have their traps in
+                * inode cache and we will catch that case on lookup.
+                */
+               err = ovl_check_layer(sb, ofs->workbasedir, "workdir");
+               if (err)
+                       return err;
+       }
+
+       for (i = 0; i < ofs->numlower; i++) {
+               err = ovl_check_layer(sb, ofs->lower_layers[i].mnt->mnt_root,
+                                     "lowerdir");
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct path upperpath = { };
@@ -1456,17 +1585,20 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
        if (ofs->config.xino != OVL_XINO_OFF)
                ofs->xino_bits = BITS_PER_LONG - 32;
 
+       /* alloc/destroy_inode needed for setting up traps in inode cache */
+       sb->s_op = &ovl_super_operations;
+
        if (ofs->config.upperdir) {
                if (!ofs->config.workdir) {
                        pr_err("overlayfs: missing 'workdir'\n");
                        goto out_err;
                }
 
-               err = ovl_get_upper(ofs, &upperpath);
+               err = ovl_get_upper(sb, ofs, &upperpath);
                if (err)
                        goto out_err;
 
-               err = ovl_get_workdir(ofs, &upperpath);
+               err = ovl_get_workdir(sb, ofs, &upperpath);
                if (err)
                        goto out_err;
 
@@ -1487,7 +1619,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
                sb->s_flags |= SB_RDONLY;
 
        if (!(ovl_force_readonly(ofs)) && ofs->config.index) {
-               err = ovl_get_indexdir(ofs, oe, &upperpath);
+               err = ovl_get_indexdir(sb, ofs, oe, &upperpath);
                if (err)
                        goto out_free_oe;
 
@@ -1500,6 +1632,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 
        }
 
+       err = ovl_check_overlapping_layers(sb, ofs);
+       if (err)
+               goto out_free_oe;
+
        /* Show index=off in /proc/mounts for forced r/o mount */
        if (!ofs->indexdir) {
                ofs->config.index = false;
@@ -1521,7 +1657,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
        cap_lower(cred->cap_effective, CAP_SYS_RESOURCE);
 
        sb->s_magic = OVERLAYFS_SUPER_MAGIC;
-       sb->s_op = &ovl_super_operations;
        sb->s_xattr = ovl_xattr_handlers;
        sb->s_fs_info = ofs;
        sb->s_flags |= SB_POSIXACL;
index 4035e64..e135064 100644 (file)
@@ -652,6 +652,18 @@ void ovl_inuse_unlock(struct dentry *dentry)
        }
 }
 
+bool ovl_is_inuse(struct dentry *dentry)
+{
+       struct inode *inode = d_inode(dentry);
+       bool inuse;
+
+       spin_lock(&inode->i_lock);
+       inuse = (inode->i_state & I_OVL_INUSE);
+       spin_unlock(&inode->i_lock);
+
+       return inuse;
+}
+
 /*
  * Does this overlay dentry need to be indexed on copy up?
  */
index 75887a2..dca07f2 100644 (file)
@@ -347,8 +347,10 @@ static void allocate_buf_for_compression(void)
 
 static void free_buf_for_compression(void)
 {
-       if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && tfm)
+       if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && tfm) {
                crypto_free_comp(tfm);
+               tfm = NULL;
+       }
        kfree(big_oops_buf);
        big_oops_buf = NULL;
        big_oops_buf_sz = 0;
@@ -606,7 +608,8 @@ int pstore_register(struct pstore_info *psi)
                return -EINVAL;
        }
 
-       allocate_buf_for_compression();
+       if (psi->flags & PSTORE_FLAGS_DMESG)
+               allocate_buf_for_compression();
 
        if (pstore_is_mounted())
                pstore_get_records(0);
index c5c6855..4310d54 100644 (file)
@@ -800,26 +800,36 @@ static int ramoops_probe(struct platform_device *pdev)
 
        cxt->pstore.data = cxt;
        /*
-        * Since bufsize is only used for dmesg crash dumps, it
-        * must match the size of the dprz record (after PRZ header
-        * and ECC bytes have been accounted for).
+        * Prepare frontend flags based on which areas are initialized.
+        * For ramoops_init_przs() cases, the "max count" variable tells
+        * if there are regions present. For ramoops_init_prz() cases,
+        * the single region size is how to check.
         */
-       cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size;
-       cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL);
-       if (!cxt->pstore.buf) {
-               pr_err("cannot allocate pstore crash dump buffer\n");
-               err = -ENOMEM;
-               goto fail_clear;
-       }
-
-       cxt->pstore.flags = PSTORE_FLAGS_DMESG;
+       cxt->pstore.flags = 0;
+       if (cxt->max_dump_cnt)
+               cxt->pstore.flags |= PSTORE_FLAGS_DMESG;
        if (cxt->console_size)
                cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE;
-       if (cxt->ftrace_size)
+       if (cxt->max_ftrace_cnt)
                cxt->pstore.flags |= PSTORE_FLAGS_FTRACE;
        if (cxt->pmsg_size)
                cxt->pstore.flags |= PSTORE_FLAGS_PMSG;
 
+       /*
+        * Since bufsize is only used for dmesg crash dumps, it
+        * must match the size of the dprz record (after PRZ header
+        * and ECC bytes have been accounted for).
+        */
+       if (cxt->pstore.flags & PSTORE_FLAGS_DMESG) {
+               cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size;
+               cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL);
+               if (!cxt->pstore.buf) {
+                       pr_err("cannot allocate pstore crash dump buffer\n");
+                       err = -ENOMEM;
+                       goto fail_clear;
+               }
+       }
+
        err = pstore_register(&cxt->pstore);
        if (err) {
                pr_err("registering with pstore failed\n");
index 693eb51..9b47117 100644 (file)
@@ -252,7 +252,8 @@ xchk_iallocbt_check_cluster(
        ir_holemask = (irec->ir_holemask & cluster_mask);
        imap.im_blkno = XFS_AGB_TO_DADDR(mp, agno, agbno);
        imap.im_len = XFS_FSB_TO_BB(mp, mp->m_blocks_per_cluster);
-       imap.im_boffset = XFS_INO_TO_OFFSET(mp, irec->ir_startino);
+       imap.im_boffset = XFS_INO_TO_OFFSET(mp, irec->ir_startino) <<
+                       mp->m_sb.sb_inodelog;
 
        if (imap.im_boffset != 0 && cluster_base != 0) {
                ASSERT(imap.im_boffset == 0 || cluster_base == 0);
index 457ced3..2466b0f 100644 (file)
@@ -2069,7 +2069,7 @@ xlog_print_tic_res(
 
        /* match with XLOG_REG_TYPE_* in xfs_log.h */
 #define REG_TYPE_STR(type, str)        [XLOG_REG_TYPE_##type] = str
-       static char *res_type_str[XLOG_REG_TYPE_MAX + 1] = {
+       static char *res_type_str[] = {
            REG_TYPE_STR(BFORMAT, "bformat"),
            REG_TYPE_STR(BCHUNK, "bchunk"),
            REG_TYPE_STR(EFI_FORMAT, "efi_format"),
@@ -2089,8 +2089,15 @@ xlog_print_tic_res(
            REG_TYPE_STR(UNMOUNT, "unmount"),
            REG_TYPE_STR(COMMIT, "commit"),
            REG_TYPE_STR(TRANSHDR, "trans header"),
-           REG_TYPE_STR(ICREATE, "inode create")
+           REG_TYPE_STR(ICREATE, "inode create"),
+           REG_TYPE_STR(RUI_FORMAT, "rui_format"),
+           REG_TYPE_STR(RUD_FORMAT, "rud_format"),
+           REG_TYPE_STR(CUI_FORMAT, "cui_format"),
+           REG_TYPE_STR(CUD_FORMAT, "cud_format"),
+           REG_TYPE_STR(BUI_FORMAT, "bui_format"),
+           REG_TYPE_STR(BUD_FORMAT, "bud_format"),
        };
+       BUILD_BUG_ON(ARRAY_SIZE(res_type_str) != XLOG_REG_TYPE_MAX + 1);
 #undef REG_TYPE_STR
 
        xfs_warn(mp, "ticket reservation summary:");
index cb3c6b3..a7f7a98 100644 (file)
@@ -238,6 +238,12 @@ int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
 #define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx)                       \
        BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_SENDMSG, t_ctx)
 
+#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr)                       \
+       BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP4_RECVMSG, NULL)
+
+#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr)                       \
+       BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_RECVMSG, NULL)
+
 #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops)                                \
 ({                                                                            \
        int __ret = 0;                                                         \
@@ -339,6 +345,8 @@ static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map,
 #define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) ({ 0; })
 #define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
 #define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
+#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr) ({ 0; })
+#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr) ({ 0; })
 #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; })
 #define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type,major,minor,access) ({ 0; })
 #define BPF_CGROUP_RUN_PROG_SYSCTL(head,table,write,buf,count,pos,nbuf) ({ 0; })
index 603a02e..e46e18c 100644 (file)
 #define SJA1105_LINKLOCAL_FILTER_B             0x011B19000000ull
 #define SJA1105_LINKLOCAL_FILTER_B_MASK                0xFFFFFF000000ull
 
-enum sja1105_frame_type {
-       SJA1105_FRAME_TYPE_NORMAL = 0,
-       SJA1105_FRAME_TYPE_LINK_LOCAL,
-};
-
-struct sja1105_skb_cb {
-       enum sja1105_frame_type type;
-};
-
-#define SJA1105_SKB_CB(skb) \
-       ((struct sja1105_skb_cb *)DSA_SKB_CB_PRIV(skb))
-
 struct sja1105_port {
        struct dsa_port *dp;
        int mgmt_slot;
index 922bb68..b25d208 100644 (file)
@@ -56,14 +56,12 @@ void __rcu_read_unlock(void);
 
 static inline void __rcu_read_lock(void)
 {
-       if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
-               preempt_disable();
+       preempt_disable();
 }
 
 static inline void __rcu_read_unlock(void)
 {
-       if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
-               preempt_enable();
+       preempt_enable();
 }
 
 static inline int rcu_preempt_depth(void)
index 178a393..50ced8a 100644 (file)
@@ -351,6 +351,8 @@ static inline void sk_psock_update_proto(struct sock *sk,
 static inline void sk_psock_restore_proto(struct sock *sk,
                                          struct sk_psock *psock)
 {
+       sk->sk_write_space = psock->saved_write_space;
+
        if (psock->sk_proto) {
                sk->sk_prot = psock->sk_proto;
                psock->sk_proto = NULL;
index 13a374f..244522b 100644 (file)
  */
 
 #define _FP_FRAC_ASSEMBLE_2(r, X, rsize)       \
-  do {                                         \
-    if (rsize <= _FP_W_TYPE_SIZE)              \
-      r = X##_f0;                              \
-    else                                       \
-      {                                                \
-       r = X##_f1;                             \
-       r <<= _FP_W_TYPE_SIZE;                  \
-       r += X##_f0;                            \
-      }                                                \
-  } while (0)
+       (void) (((rsize) <= _FP_W_TYPE_SIZE)    \
+               ? ({ (r) = X##_f0; })           \
+               : ({                            \
+                    (r) = X##_f1;              \
+                    (r) <<= _FP_W_TYPE_SIZE;   \
+                    (r) += X##_f0;             \
+                   }))
 
 #define _FP_FRAC_DISASSEMBLE_2(X, r, rsize)                            \
   do {                                                                 \
index 6bdf8c6..f37d128 100644 (file)
@@ -795,11 +795,12 @@ do {                                                                      \
          ur_ = (unsigned rtype) -r;                                    \
        else                                                            \
          ur_ = (unsigned rtype) r;                                     \
-       if (rsize <= _FP_W_TYPE_SIZE)                                   \
-         __FP_CLZ(X##_e, ur_);                                         \
-       else                                                            \
-         __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE),       \
-                    (_FP_W_TYPE)ur_);                                  \
+       (void) (((rsize) <= _FP_W_TYPE_SIZE)                            \
+               ? ({ __FP_CLZ(X##_e, ur_); })                           \
+               : ({                                                    \
+                    __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE),  \
+                                                           (_FP_W_TYPE)ur_); \
+                 }));                                                  \
        if (rsize < _FP_W_TYPE_SIZE)                                    \
                X##_e -= (_FP_W_TYPE_SIZE - rsize);                     \
        X##_e = rsize - X##_e - 1;                                      \
index 3fbc989..855b352 100644 (file)
@@ -259,8 +259,7 @@ static inline u32 rt6_get_cookie(const struct rt6_info *rt)
        rcu_read_lock();
 
        from = rcu_dereference(rt->from);
-       if (from && (rt->rt6i_flags & RTF_PCPU ||
-           unlikely(!list_empty(&rt->rt6i_uncached))))
+       if (from)
                fib6_get_cookie_safe(from, &cookie);
 
        rcu_read_unlock();
index 39ea62f..4a55ce6 100644 (file)
@@ -209,6 +209,10 @@ struct tls_offload_context_tx {
        (ALIGN(sizeof(struct tls_offload_context_tx), sizeof(void *)) +        \
         TLS_DRIVER_STATE_SIZE)
 
+enum tls_context_flags {
+       TLS_RX_SYNC_RUNNING = 0,
+};
+
 struct cipher_context {
        char *iv;
        char *rec_seq;
index 0742095..5487308 100644 (file)
@@ -2698,6 +2698,7 @@ struct ib_client {
        const char *name;
        void (*add)   (struct ib_device *);
        void (*remove)(struct ib_device *, void *client_data);
+       void (*rename)(struct ib_device *dev, void *client_data);
 
        /* Returns the net_dev belonging to this ib_client and matching the
         * given parameters.
index 63e0cf6..e4114a7 100644 (file)
@@ -192,6 +192,8 @@ enum bpf_attach_type {
        BPF_LIRC_MODE2,
        BPF_FLOW_DISSECTOR,
        BPF_CGROUP_SYSCTL,
+       BPF_CGROUP_UDP4_RECVMSG,
+       BPF_CGROUP_UDP6_RECVMSG,
        __MAX_BPF_ATTACH_TYPE
 };
 
index 19fb55e..2971d29 100644 (file)
  *  7.30
  *  - add FUSE_EXPLICIT_INVAL_DATA
  *  - add FUSE_IOCTL_COMPAT_X32
+ *
+ *  7.31
+ *  - add FUSE_WRITE_KILL_PRIV flag
  */
 
 #ifndef _LINUX_FUSE_H
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 30
+#define FUSE_KERNEL_MINOR_VERSION 31
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -327,9 +330,11 @@ struct fuse_file_lock {
  *
  * FUSE_WRITE_CACHE: delayed write from page cache, file handle is guessed
  * FUSE_WRITE_LOCKOWNER: lock_owner field is valid
+ * FUSE_WRITE_KILL_PRIV: kill suid and sgid bits
  */
 #define FUSE_WRITE_CACHE       (1 << 0)
 #define FUSE_WRITE_LOCKOWNER   (1 << 1)
+#define FUSE_WRITE_KILL_PRIV   (1 << 2)
 
 /**
  * Read flags
index cb5440b..e8ba3a1 100644 (file)
@@ -1581,6 +1581,8 @@ bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type,
                case BPF_CGROUP_INET6_CONNECT:
                case BPF_CGROUP_UDP4_SENDMSG:
                case BPF_CGROUP_UDP6_SENDMSG:
+               case BPF_CGROUP_UDP4_RECVMSG:
+               case BPF_CGROUP_UDP6_RECVMSG:
                        return 0;
                default:
                        return -EINVAL;
@@ -1875,6 +1877,8 @@ static int bpf_prog_attach(const union bpf_attr *attr)
        case BPF_CGROUP_INET6_CONNECT:
        case BPF_CGROUP_UDP4_SENDMSG:
        case BPF_CGROUP_UDP6_SENDMSG:
+       case BPF_CGROUP_UDP4_RECVMSG:
+       case BPF_CGROUP_UDP6_RECVMSG:
                ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
                break;
        case BPF_CGROUP_SOCK_OPS:
@@ -1960,6 +1964,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
        case BPF_CGROUP_INET6_CONNECT:
        case BPF_CGROUP_UDP4_SENDMSG:
        case BPF_CGROUP_UDP6_SENDMSG:
+       case BPF_CGROUP_UDP4_RECVMSG:
+       case BPF_CGROUP_UDP6_RECVMSG:
                ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
                break;
        case BPF_CGROUP_SOCK_OPS:
@@ -2011,6 +2017,8 @@ static int bpf_prog_query(const union bpf_attr *attr,
        case BPF_CGROUP_INET6_CONNECT:
        case BPF_CGROUP_UDP4_SENDMSG:
        case BPF_CGROUP_UDP6_SENDMSG:
+       case BPF_CGROUP_UDP4_RECVMSG:
+       case BPF_CGROUP_UDP6_RECVMSG:
        case BPF_CGROUP_SOCK_OPS:
        case BPF_CGROUP_DEVICE:
        case BPF_CGROUP_SYSCTL:
index 95f9354..d2c8a66 100644 (file)
@@ -5361,9 +5361,12 @@ static int check_return_code(struct bpf_verifier_env *env)
        struct tnum range = tnum_range(0, 1);
 
        switch (env->prog->type) {
+       case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
+               if (env->prog->expected_attach_type == BPF_CGROUP_UDP4_RECVMSG ||
+                   env->prog->expected_attach_type == BPF_CGROUP_UDP6_RECVMSG)
+                       range = tnum_range(1, 1);
        case BPF_PROG_TYPE_CGROUP_SKB:
        case BPF_PROG_TYPE_CGROUP_SOCK:
-       case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
        case BPF_PROG_TYPE_SOCK_OPS:
        case BPF_PROG_TYPE_CGROUP_DEVICE:
        case BPF_PROG_TYPE_CGROUP_SYSCTL:
@@ -5380,16 +5383,17 @@ static int check_return_code(struct bpf_verifier_env *env)
        }
 
        if (!tnum_in(range, reg->var_off)) {
+               char tn_buf[48];
+
                verbose(env, "At program exit the register R0 ");
                if (!tnum_is_unknown(reg->var_off)) {
-                       char tn_buf[48];
-
                        tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
                        verbose(env, "has value %s", tn_buf);
                } else {
                        verbose(env, "has unknown scalar value");
                }
-               verbose(env, " should have been 0 or 1\n");
+               tnum_strn(tn_buf, sizeof(tn_buf), range);
+               verbose(env, " should have been in %s\n", tn_buf);
                return -EINVAL;
        }
        return 0;
index 328a01e..d622eac 100644 (file)
@@ -3621,12 +3621,11 @@ static struct pid *pidfd_to_pid(const struct file *file)
 }
 
 /**
- * sys_pidfd_send_signal - send a signal to a process through a task file
- *                          descriptor
- * @pidfd:  the file descriptor of the process
- * @sig:    signal to be sent
- * @info:   the signal info
- * @flags:  future flags to be passed
+ * sys_pidfd_send_signal - Signal a process through a pidfd
+ * @pidfd:  file descriptor of the process
+ * @sig:    signal to send
+ * @info:   signal info
+ * @flags:  future flags
  *
  * The syscall currently only signals via PIDTYPE_PID which covers
  * kill(<positive-pid>, <signal>. It does not signal threads or process
index e8fd5dc..80281ef 100644 (file)
@@ -99,6 +99,7 @@ EXPORT_SYMBOL(can_ioctl);
 static void can_sock_destruct(struct sock *sk)
 {
        skb_queue_purge(&sk->sk_receive_queue);
+       skb_queue_purge(&sk->sk_error_queue);
 }
 
 static const struct can_proto *can_get_proto(int protocol)
@@ -952,6 +953,8 @@ static struct pernet_operations can_pernet_ops __read_mostly = {
 
 static __init int can_init(void)
 {
+       int err;
+
        /* check for correct padding to be able to use the structs similarly */
        BUILD_BUG_ON(offsetof(struct can_frame, can_dlc) !=
                     offsetof(struct canfd_frame, len) ||
@@ -965,15 +968,31 @@ static __init int can_init(void)
        if (!rcv_cache)
                return -ENOMEM;
 
-       register_pernet_subsys(&can_pernet_ops);
+       err = register_pernet_subsys(&can_pernet_ops);
+       if (err)
+               goto out_pernet;
 
        /* protocol register */
-       sock_register(&can_family_ops);
-       register_netdevice_notifier(&can_netdev_notifier);
+       err = sock_register(&can_family_ops);
+       if (err)
+               goto out_sock;
+       err = register_netdevice_notifier(&can_netdev_notifier);
+       if (err)
+               goto out_notifier;
+
        dev_add_pack(&can_packet);
        dev_add_pack(&canfd_packet);
 
        return 0;
+
+out_notifier:
+       sock_unregister(PF_CAN);
+out_sock:
+       unregister_pernet_subsys(&can_pernet_ops);
+out_pernet:
+       kmem_cache_destroy(rcv_cache);
+
+       return err;
 }
 
 static __exit void can_exit(void)
index 140858d..eb7fb6d 100644 (file)
@@ -5021,12 +5021,12 @@ static inline void __netif_receive_skb_list_ptype(struct list_head *head,
        if (list_empty(head))
                return;
        if (pt_prev->list_func != NULL)
-               pt_prev->list_func(head, pt_prev, orig_dev);
+               INDIRECT_CALL_INET(pt_prev->list_func, ipv6_list_rcv,
+                                  ip_list_rcv, head, pt_prev, orig_dev);
        else
                list_for_each_entry_safe(skb, next, head, list) {
                        skb_list_del_init(skb);
-                       INDIRECT_CALL_INET(pt_prev->func, ipv6_rcv, ip_rcv, skb,
-                                          skb->dev, pt_prev, orig_dev);
+                       pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
                }
 }
 
index 6dadeff..d08b1e1 100644 (file)
@@ -1355,13 +1355,16 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
        if (!regbuf)
                return -ENOMEM;
 
+       if (regs.len < reglen)
+               reglen = regs.len;
+
        ops->get_regs(dev, &regs, regbuf);
 
        ret = -EFAULT;
        if (copy_to_user(useraddr, &regs, sizeof(regs)))
                goto out;
        useraddr += offsetof(struct ethtool_regs, data);
-       if (regbuf && copy_to_user(useraddr, regbuf, regs.len))
+       if (copy_to_user(useraddr, regbuf, reglen))
                goto out;
        ret = 0;
 
index 43f0115..18f8dd8 100644 (file)
@@ -757,9 +757,9 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (err)
                goto errout;
 
-       if (rule_exists(ops, frh, tb, rule)) {
-               if (nlh->nlmsg_flags & NLM_F_EXCL)
-                       err = -EEXIST;
+       if ((nlh->nlmsg_flags & NLM_F_EXCL) &&
+           rule_exists(ops, frh, tb, rule)) {
+               err = -EEXIST;
                goto errout_free;
        }
 
index cd09bf5..f615e42 100644 (file)
@@ -5300,7 +5300,13 @@ __bpf_skc_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
        struct net *net;
        int sdif;
 
-       family = len == sizeof(tuple->ipv4) ? AF_INET : AF_INET6;
+       if (len == sizeof(tuple->ipv4))
+               family = AF_INET;
+       else if (len == sizeof(tuple->ipv6))
+               family = AF_INET6;
+       else
+               return NULL;
+
        if (unlikely(family == AF_UNSPEC || flags ||
                     !((s32)netns_id < 0 || netns_id <= S32_MAX)))
                goto out;
@@ -5333,8 +5339,14 @@ __bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
        struct sock *sk = __bpf_skc_lookup(skb, tuple, len, caller_net,
                                           ifindex, proto, netns_id, flags);
 
-       if (sk)
+       if (sk) {
                sk = sk_to_full_sk(sk);
+               if (!sk_fullsock(sk)) {
+                       if (!sock_flag(sk, SOCK_RCU_FREE))
+                               sock_gen_put(sk);
+                       return NULL;
+               }
+       }
 
        return sk;
 }
@@ -5365,8 +5377,14 @@ bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
        struct sock *sk = bpf_skc_lookup(skb, tuple, len, proto, netns_id,
                                         flags);
 
-       if (sk)
+       if (sk) {
                sk = sk_to_full_sk(sk);
+               if (!sk_fullsock(sk)) {
+                       if (!sock_flag(sk, SOCK_RCU_FREE))
+                               sock_gen_put(sk);
+                       return NULL;
+               }
+       }
 
        return sk;
 }
@@ -6726,6 +6744,7 @@ static bool sock_addr_is_valid_access(int off, int size,
                case BPF_CGROUP_INET4_BIND:
                case BPF_CGROUP_INET4_CONNECT:
                case BPF_CGROUP_UDP4_SENDMSG:
+               case BPF_CGROUP_UDP4_RECVMSG:
                        break;
                default:
                        return false;
@@ -6736,6 +6755,7 @@ static bool sock_addr_is_valid_access(int off, int size,
                case BPF_CGROUP_INET6_BIND:
                case BPF_CGROUP_INET6_CONNECT:
                case BPF_CGROUP_UDP6_SENDMSG:
+               case BPF_CGROUP_UDP6_RECVMSG:
                        break;
                default:
                        return false;
index 99ddc69..f975c5e 100644 (file)
@@ -3059,7 +3059,13 @@ static int pktgen_wait_thread_run(struct pktgen_thread *t)
 {
        while (thread_is_running(t)) {
 
+               /* note: 't' will still be around even after the unlock/lock
+                * cycle because pktgen_thread threads are only cleared at
+                * net exit
+                */
+               mutex_unlock(&pktgen_thread_lock);
                msleep_interruptible(100);
+               mutex_lock(&pktgen_thread_lock);
 
                if (signal_pending(current))
                        goto signal;
@@ -3074,6 +3080,10 @@ static int pktgen_wait_all_threads_run(struct pktgen_net *pn)
        struct pktgen_thread *t;
        int sig = 1;
 
+       /* prevent from racing with rmmod */
+       if (!try_module_get(THIS_MODULE))
+               return sig;
+
        mutex_lock(&pktgen_thread_lock);
 
        list_for_each_entry(t, &pn->pktgen_threads, th_list) {
@@ -3087,6 +3097,7 @@ static int pktgen_wait_all_threads_run(struct pktgen_net *pn)
                        t->control |= (T_STOP);
 
        mutex_unlock(&pktgen_thread_lock);
+       module_put(THIS_MODULE);
        return sig;
 }
 
index 47c1aa9..c8cd99c 100644 (file)
@@ -2337,6 +2337,7 @@ do_frag_list:
                kv.iov_base = skb->data + offset;
                kv.iov_len = slen;
                memset(&msg, 0, sizeof(msg));
+               msg.msg_flags = MSG_DONTWAIT;
 
                ret = kernel_sendmsg_locked(sk, &msg, &kv, 1, slen);
                if (ret <= 0)
index 969402c..d43737e 100644 (file)
@@ -28,14 +28,10 @@ static inline bool sja1105_is_link_local(const struct sk_buff *skb)
  */
 static bool sja1105_filter(const struct sk_buff *skb, struct net_device *dev)
 {
-       if (sja1105_is_link_local(skb)) {
-               SJA1105_SKB_CB(skb)->type = SJA1105_FRAME_TYPE_LINK_LOCAL;
+       if (sja1105_is_link_local(skb))
                return true;
-       }
-       if (!dsa_port_is_vlan_filtering(dev->dsa_ptr)) {
-               SJA1105_SKB_CB(skb)->type = SJA1105_FRAME_TYPE_NORMAL;
+       if (!dsa_port_is_vlan_filtering(dev->dsa_ptr))
                return true;
-       }
        return false;
 }
 
@@ -84,7 +80,7 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
 
        skb->offload_fwd_mark = 1;
 
-       if (SJA1105_SKB_CB(skb)->type == SJA1105_FRAME_TYPE_LINK_LOCAL) {
+       if (sja1105_is_link_local(skb)) {
                /* Management traffic path. Switch embeds the switch ID and
                 * port ID into bytes of the destination MAC, courtesy of
                 * the incl_srcpt options.
index b804106..bfa49a8 100644 (file)
@@ -964,7 +964,7 @@ static int fib_check_nh_v4_gw(struct net *net, struct fib_nh *nh, u32 table,
 {
        struct net_device *dev;
        struct fib_result res;
-       int err;
+       int err = 0;
 
        if (nh->fib_nh_flags & RTNH_F_ONLINK) {
                unsigned int addr_type;
index cee6402..6cb7cff 100644 (file)
@@ -1981,7 +1981,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        u32             itag = 0;
        struct rtable   *rth;
        struct flowi4   fl4;
-       bool do_cache;
+       bool do_cache = true;
 
        /* IP on this device is disabled. */
 
@@ -2058,6 +2058,9 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        if (res->type == RTN_BROADCAST) {
                if (IN_DEV_BFORWARD(in_dev))
                        goto make_route;
+               /* not do cache if bc_forwarding is enabled */
+               if (IPV4_DEVCONF_ALL(net, BC_FORWARDING))
+                       do_cache = false;
                goto brd_input;
        }
 
@@ -2095,18 +2098,15 @@ brd_input:
        RT_CACHE_STAT_INC(in_brd);
 
 local_input:
-       do_cache = false;
-       if (res->fi) {
-               if (!itag) {
-                       struct fib_nh_common *nhc = FIB_RES_NHC(*res);
+       do_cache &= res->fi && !itag;
+       if (do_cache) {
+               struct fib_nh_common *nhc = FIB_RES_NHC(*res);
 
-                       rth = rcu_dereference(nhc->nhc_rth_input);
-                       if (rt_cache_valid(rth)) {
-                               skb_dst_set_noref(skb, &rth->dst);
-                               err = 0;
-                               goto out;
-                       }
-                       do_cache = true;
+               rth = rcu_dereference(nhc->nhc_rth_input);
+               if (rt_cache_valid(rth)) {
+                       skb_dst_set_noref(skb, &rth->dst);
+                       err = 0;
+                       goto out;
                }
        }
 
index 1891443..eed59c8 100644 (file)
@@ -498,7 +498,11 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
 struct sock *udp4_lib_lookup_skb(struct sk_buff *skb,
                                 __be16 sport, __be16 dport)
 {
-       return __udp4_lib_lookup_skb(skb, sport, dport, &udp_table);
+       const struct iphdr *iph = ip_hdr(skb);
+
+       return __udp4_lib_lookup(dev_net(skb->dev), iph->saddr, sport,
+                                iph->daddr, dport, inet_iif(skb),
+                                inet_sdif(skb), &udp_table, NULL);
 }
 EXPORT_SYMBOL_GPL(udp4_lib_lookup_skb);
 
@@ -533,8 +537,7 @@ static inline bool __udp_is_mcast_sock(struct net *net, struct sock *sk,
            (inet->inet_dport != rmt_port && inet->inet_dport) ||
            (inet->inet_rcv_saddr && inet->inet_rcv_saddr != loc_addr) ||
            ipv6_only_sock(sk) ||
-           (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif &&
-            sk->sk_bound_dev_if != sdif))
+           !udp_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif))
                return false;
        if (!ip_mc_sf_allow(sk, loc_addr, rmt_addr, dif, sdif))
                return false;
@@ -1774,6 +1777,10 @@ try_again:
                sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
                memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
                *addr_len = sizeof(*sin);
+
+               if (cgroup_bpf_enabled)
+                       BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk,
+                                                       (struct sockaddr *)sin);
        }
 
        if (udp_sk(sk)->gro_enabled)
index 2f3eb7d..545e339 100644 (file)
@@ -250,9 +250,9 @@ struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label)
        rcu_read_lock_bh();
        for_each_sk_fl_rcu(np, sfl) {
                struct ip6_flowlabel *fl = sfl->fl;
-               if (fl->label == label) {
+
+               if (fl->label == label && atomic_inc_not_zero(&fl->users)) {
                        fl->lastuse = jiffies;
-                       atomic_inc(&fl->users);
                        rcu_read_unlock_bh();
                        return fl;
                }
@@ -618,7 +618,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
                                                goto done;
                                        }
                                        fl1 = sfl->fl;
-                                       atomic_inc(&fl1->users);
+                                       if (!atomic_inc_not_zero(&fl1->users))
+                                               fl1 = NULL;
                                        break;
                                }
                        }
index 703c838..70693bc 100644 (file)
@@ -779,6 +779,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        struct flowi6 fl6;
        struct ipcm6_cookie ipc6;
        int addr_len = msg->msg_namelen;
+       int hdrincl;
        u16 proto;
        int err;
 
@@ -792,6 +793,13 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        if (msg->msg_flags & MSG_OOB)
                return -EOPNOTSUPP;
 
+       /* hdrincl should be READ_ONCE(inet->hdrincl)
+        * but READ_ONCE() doesn't work with bit fields.
+        * Doing this indirectly yields the same result.
+        */
+       hdrincl = inet->hdrincl;
+       hdrincl = READ_ONCE(hdrincl);
+
        /*
         *      Get and verify the address.
         */
@@ -883,11 +891,14 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        opt = ipv6_fixup_options(&opt_space, opt);
 
        fl6.flowi6_proto = proto;
-       rfv.msg = msg;
-       rfv.hlen = 0;
-       err = rawv6_probe_proto_opt(&rfv, &fl6);
-       if (err)
-               goto out;
+
+       if (!hdrincl) {
+               rfv.msg = msg;
+               rfv.hlen = 0;
+               err = rawv6_probe_proto_opt(&rfv, &fl6);
+               if (err)
+                       goto out;
+       }
 
        if (!ipv6_addr_any(daddr))
                fl6.daddr = *daddr;
@@ -904,7 +915,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                fl6.flowi6_oif = np->ucast_oif;
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-       if (inet->hdrincl)
+       if (hdrincl)
                fl6.flowi6_flags |= FLOWI_FLAG_KNOWN_NH;
 
        if (ipc6.tclass < 0)
@@ -927,7 +938,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                goto do_confirm;
 
 back_from_confirm:
-       if (inet->hdrincl)
+       if (hdrincl)
                err = rawv6_send_hdrinc(sk, msg, len, &fl6, &dst,
                                        msg->msg_flags, &ipc6.sockc);
        else {
index b3418a7..70b01bd 100644 (file)
@@ -239,7 +239,7 @@ struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
 
        return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport,
                                 &iph->daddr, dport, inet6_iif(skb),
-                                inet6_sdif(skb), &udp_table, skb);
+                                inet6_sdif(skb), &udp_table, NULL);
 }
 EXPORT_SYMBOL_GPL(udp6_lib_lookup_skb);
 
@@ -365,6 +365,10 @@ try_again:
                                                    inet6_iif(skb));
                }
                *addr_len = sizeof(*sin6);
+
+               if (cgroup_bpf_enabled)
+                       BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk,
+                                               (struct sockaddr *)sin6);
        }
 
        if (udp_sk(sk)->gro_enabled)
@@ -511,7 +515,7 @@ int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        struct net *net = dev_net(skb->dev);
 
        sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source,
-                              inet6_iif(skb), inet6_sdif(skb), udptable, skb);
+                              inet6_iif(skb), inet6_sdif(skb), udptable, NULL);
        if (!sk) {
                /* No socket for error: try tunnels before discarding */
                sk = ERR_PTR(-ENOENT);
index 5005961..d25e91d 100644 (file)
@@ -23,7 +23,7 @@
 #include "internal.h"
 
 static const struct nla_policy mpls_iptunnel_policy[MPLS_IPTUNNEL_MAX + 1] = {
-       [MPLS_IPTUNNEL_DST]     = { .type = NLA_U32 },
+       [MPLS_IPTUNNEL_DST]     = { .len = sizeof(u32) },
        [MPLS_IPTUNNEL_TTL]     = { .type = NLA_U8 },
 };
 
index fc012e8..a29d66d 100644 (file)
@@ -3008,8 +3008,8 @@ static int packet_release(struct socket *sock)
 
        synchronize_net();
 
+       kfree(po->rollover);
        if (f) {
-               kfree(po->rollover);
                fanout_release_data(f);
                kfree(f);
        }
index 2da9b75..b8d581b 100644 (file)
@@ -87,7 +87,7 @@ static void rds_ib_dev_shutdown(struct rds_ib_device *rds_ibdev)
 
        spin_lock_irqsave(&rds_ibdev->spinlock, flags);
        list_for_each_entry(ic, &rds_ibdev->conn_list, ib_node)
-               rds_conn_drop(ic->conn);
+               rds_conn_path_drop(&ic->conn->c_path[0], true);
        spin_unlock_irqrestore(&rds_ibdev->spinlock, flags);
 }
 
index d664e9a..0b347f4 100644 (file)
@@ -428,12 +428,14 @@ int rds_ib_flush_mr_pool(struct rds_ib_mr_pool *pool,
                wait_clean_list_grace();
 
                list_to_llist_nodes(pool, &unmap_list, &clean_nodes, &clean_tail);
-               if (ibmr_ret)
+               if (ibmr_ret) {
                        *ibmr_ret = llist_entry(clean_nodes, struct rds_ib_mr, llnode);
-
+                       clean_nodes = clean_nodes->next;
+               }
                /* more than one entry in llist nodes */
-               if (clean_nodes->next)
-                       llist_add_batch(clean_nodes->next, clean_tail, &pool->clean_list);
+               if (clean_nodes)
+                       llist_add_batch(clean_nodes, clean_tail,
+                                       &pool->clean_list);
 
        }
 
index 8946c89..3cae88c 100644 (file)
@@ -168,6 +168,7 @@ void rds_ib_recv_free_caches(struct rds_ib_connection *ic)
                list_del(&inc->ii_cache_entry);
                WARN_ON(!list_empty(&inc->ii_frags));
                kmem_cache_free(rds_ib_incoming_slab, inc);
+               atomic_dec(&rds_ib_allocation);
        }
 
        rds_ib_cache_xfer_to_ready(&ic->i_cache_frags);
@@ -1057,6 +1058,8 @@ out:
 
 void rds_ib_recv_exit(void)
 {
+       WARN_ON(atomic_read(&rds_ib_allocation));
+
        kmem_cache_destroy(rds_ib_incoming_slab);
        kmem_cache_destroy(rds_ib_frag_slab);
 }
index 92331e1..f17908f 100644 (file)
@@ -2312,7 +2312,6 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk,
        union sctp_addr addr;
        struct sctp_af *af;
        int src_match = 0;
-       char *cookie;
 
        /* We must include the address that the INIT packet came from.
         * This is the only address that matters for an INIT packet.
@@ -2416,14 +2415,6 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk,
        /* Peer Rwnd   : Current calculated value of the peer's rwnd.  */
        asoc->peer.rwnd = asoc->peer.i.a_rwnd;
 
-       /* Copy cookie in case we need to resend COOKIE-ECHO. */
-       cookie = asoc->peer.cookie;
-       if (cookie) {
-               asoc->peer.cookie = kmemdup(cookie, asoc->peer.cookie_len, gfp);
-               if (!asoc->peer.cookie)
-                       goto clean_up;
-       }
-
        /* RFC 2960 7.2.1 The initial value of ssthresh MAY be arbitrarily
         * high (for example, implementations MAY use the size of the receiver
         * advertised window).
@@ -2592,7 +2583,9 @@ do_addr_param:
        case SCTP_PARAM_STATE_COOKIE:
                asoc->peer.cookie_len =
                        ntohs(param.p->length) - sizeof(struct sctp_paramhdr);
-               asoc->peer.cookie = param.cookie->body;
+               asoc->peer.cookie = kmemdup(param.cookie->body, asoc->peer.cookie_len, gfp);
+               if (!asoc->peer.cookie)
+                       retval = 0;
                break;
 
        case SCTP_PARAM_HEARTBEAT_INFO:
index 9b50da5..a554d6d 100644 (file)
@@ -883,6 +883,11 @@ static void sctp_cmd_new_state(struct sctp_cmd_seq *cmds,
                                                asoc->rto_initial;
        }
 
+       if (sctp_state(asoc, ESTABLISHED)) {
+               kfree(asoc->peer.cookie);
+               asoc->peer.cookie = NULL;
+       }
+
        if (sctp_state(asoc, ESTABLISHED) ||
            sctp_state(asoc, CLOSED) ||
            sctp_state(asoc, SHUTDOWN_RECEIVED)) {
index d6e57da..627a87a 100644 (file)
@@ -2288,13 +2288,13 @@ call_status(struct rpc_task *task)
        case -ECONNREFUSED:
        case -ECONNRESET:
        case -ECONNABORTED:
+       case -ENOTCONN:
                rpc_force_rebind(clnt);
                /* fall through */
        case -EADDRINUSE:
                rpc_delay(task, 3*HZ);
                /* fall through */
        case -EPIPE:
-       case -ENOTCONN:
        case -EAGAIN:
                break;
        case -EIO:
@@ -2426,17 +2426,21 @@ call_decode(struct rpc_task *task)
                return;
        case -EAGAIN:
                task->tk_status = 0;
-               /* Note: rpc_decode_header() may have freed the RPC slot */
-               if (task->tk_rqstp == req) {
-                       xdr_free_bvec(&req->rq_rcv_buf);
-                       req->rq_reply_bytes_recvd = 0;
-                       req->rq_rcv_buf.len = 0;
-                       if (task->tk_client->cl_discrtry)
-                               xprt_conditional_disconnect(req->rq_xprt,
-                                                           req->rq_connect_cookie);
-               }
+               xdr_free_bvec(&req->rq_rcv_buf);
+               req->rq_reply_bytes_recvd = 0;
+               req->rq_rcv_buf.len = 0;
+               if (task->tk_client->cl_discrtry)
+                       xprt_conditional_disconnect(req->rq_xprt,
+                                                   req->rq_connect_cookie);
                task->tk_action = call_encode;
                rpc_check_timeout(task);
+               break;
+       case -EKEYREJECTED:
+               task->tk_action = call_reserve;
+               rpc_check_timeout(task);
+               rpcauth_invalcred(task);
+               /* Ensure we obtain a new XID if we retry! */
+               xprt_release(task);
        }
 }
 
@@ -2572,11 +2576,7 @@ out_msg_denied:
                        break;
                task->tk_cred_retry--;
                trace_rpc__stale_creds(task);
-               rpcauth_invalcred(task);
-               /* Ensure we obtain a new XID! */
-               xprt_release(task);
-               task->tk_action = call_reserve;
-               return -EAGAIN;
+               return -EKEYREJECTED;
        case rpc_autherr_badcred:
        case rpc_autherr_badverf:
                /* possibly garbled cred/verf? */
index bef5eac..84bb379 100644 (file)
@@ -810,8 +810,7 @@ static struct rpcrdma_sendctx *rpcrdma_sendctx_create(struct rpcrdma_ia *ia)
 {
        struct rpcrdma_sendctx *sc;
 
-       sc = kzalloc(sizeof(*sc) +
-                    ia->ri_max_send_sges * sizeof(struct ib_sge),
+       sc = kzalloc(struct_size(sc, sc_sges, ia->ri_max_send_sges),
                     GFP_KERNEL);
        if (!sc)
                return NULL;
index b95c408..1f9cf57 100644 (file)
@@ -550,11 +550,23 @@ void tls_device_write_space(struct sock *sk, struct tls_context *ctx)
        }
 }
 
+static void tls_device_resync_rx(struct tls_context *tls_ctx,
+                                struct sock *sk, u32 seq, u64 rcd_sn)
+{
+       struct net_device *netdev;
+
+       if (WARN_ON(test_and_set_bit(TLS_RX_SYNC_RUNNING, &tls_ctx->flags)))
+               return;
+       netdev = READ_ONCE(tls_ctx->netdev);
+       if (netdev)
+               netdev->tlsdev_ops->tls_dev_resync_rx(netdev, sk, seq, rcd_sn);
+       clear_bit_unlock(TLS_RX_SYNC_RUNNING, &tls_ctx->flags);
+}
+
 void handle_device_resync(struct sock *sk, u32 seq, u64 rcd_sn)
 {
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_offload_context_rx *rx_ctx;
-       struct net_device *netdev;
        u32 is_req_pending;
        s64 resync_req;
        u32 req_seq;
@@ -570,12 +582,7 @@ void handle_device_resync(struct sock *sk, u32 seq, u64 rcd_sn)
        if (unlikely(is_req_pending) && req_seq == seq &&
            atomic64_try_cmpxchg(&rx_ctx->resync_req, &resync_req, 0)) {
                seq += TLS_HEADER_SIZE - 1;
-               down_read(&device_offload_lock);
-               netdev = tls_ctx->netdev;
-               if (netdev)
-                       netdev->tlsdev_ops->tls_dev_resync_rx(netdev, sk, seq,
-                                                             rcd_sn);
-               up_read(&device_offload_lock);
+               tls_device_resync_rx(tls_ctx, sk, seq, rcd_sn);
        }
 }
 
@@ -977,7 +984,10 @@ static int tls_device_down(struct net_device *netdev)
                if (ctx->rx_conf == TLS_HW)
                        netdev->tlsdev_ops->tls_dev_del(netdev, ctx,
                                                        TLS_OFFLOAD_CTX_DIR_RX);
-               ctx->netdev = NULL;
+               WRITE_ONCE(ctx->netdev, NULL);
+               smp_mb__before_atomic(); /* pairs with test_and_set_bit() */
+               while (test_bit(TLS_RX_SYNC_RUNNING, &ctx->flags))
+                       usleep_range(10, 200);
                dev_put(netdev);
                list_del_init(&ctx->list);
 
index eae7b63..6e87cc8 100644 (file)
@@ -678,7 +678,7 @@ void read_trace_pipe(void)
                static char buf[4096];
                ssize_t sz;
 
-               sz = read(trace_fd, buf, sizeof(buf));
+               sz = read(trace_fd, buf, sizeof(buf) - 1);
                if (sz > 0) {
                        buf[sz] = 0;
                        puts(buf);
index aff2b4a..e399380 100644 (file)
@@ -216,7 +216,7 @@ static int test_debug_fs_uprobe(char *binary_path, long offset, bool is_return)
 {
        const char *event_type = "uprobe";
        struct perf_event_attr attr = {};
-       char buf[256], event_alias[256];
+       char buf[256], event_alias[sizeof("test_1234567890")];
        __u64 probe_offset, probe_addr;
        __u32 len, prog_id, fd_type;
        int err, res, kfd, efd;
index 640f5f7..14b4544 100644 (file)
 #define CLONE_PIDFD 0x00001000
 #endif
 
+#ifndef __NR_pidfd_send_signal
+#define __NR_pidfd_send_signal -1
+#endif
+
 static int do_child(void *args)
 {
        printf("%d\n", getpid());
index ac26876..e744b3e 100644 (file)
@@ -29,7 +29,7 @@ CGROUP COMMANDS
 |      *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
 |      *ATTACH_TYPE* := { **ingress** | **egress** | **sock_create** | **sock_ops** | **device** |
 |              **bind4** | **bind6** | **post_bind4** | **post_bind6** | **connect4** | **connect6** |
-|              **sendmsg4** | **sendmsg6** | **sysctl** }
+|              **sendmsg4** | **sendmsg6** | **recvmsg4** | **recvmsg6** | **sysctl** }
 |      *ATTACH_FLAGS* := { **multi** | **override** }
 
 DESCRIPTION
@@ -86,6 +86,10 @@ DESCRIPTION
                  unconnected udp4 socket (since 4.18);
                  **sendmsg6** call to sendto(2), sendmsg(2), sendmmsg(2) for an
                  unconnected udp6 socket (since 4.18);
+                 **recvmsg4** call to recvfrom(2), recvmsg(2), recvmmsg(2) for
+                  an unconnected udp4 socket (since 5.2);
+                 **recvmsg6** call to recvfrom(2), recvmsg(2), recvmmsg(2) for
+                  an unconnected udp6 socket (since 5.2);
                  **sysctl** sysctl access (since 5.2).
 
        **bpftool cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG*
index e811854..018ecef 100644 (file)
@@ -40,7 +40,7 @@ PROG COMMANDS
 |              **lwt_seg6local** | **sockops** | **sk_skb** | **sk_msg** | **lirc_mode2** |
 |              **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** |
 |              **cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6** |
-|              **cgroup/sysctl**
+|              **cgroup/recvmsg4** | **cgroup/recvmsg6** | **cgroup/sysctl**
 |      }
 |       *ATTACH_TYPE* := {
 |              **msg_verdict** | **stream_verdict** | **stream_parser** | **flow_dissector**
index 50e402a..4300adf 100644 (file)
@@ -371,6 +371,7 @@ _bpftool()
                                 lirc_mode2 cgroup/bind4 cgroup/bind6 \
                                 cgroup/connect4 cgroup/connect6 \
                                 cgroup/sendmsg4 cgroup/sendmsg6 \
+                                cgroup/recvmsg4 cgroup/recvmsg6 \
                                 cgroup/post_bind4 cgroup/post_bind6 \
                                 cgroup/sysctl" -- \
                                                    "$cur" ) )
@@ -666,7 +667,7 @@ _bpftool()
                 attach|detach)
                     local ATTACH_TYPES='ingress egress sock_create sock_ops \
                         device bind4 bind6 post_bind4 post_bind6 connect4 \
-                        connect6 sendmsg4 sendmsg6 sysctl'
+                        connect6 sendmsg4 sendmsg6 recvmsg4 recvmsg6 sysctl'
                     local ATTACH_FLAGS='multi override'
                     local PROG_TYPE='id pinned tag'
                     case $prev in
@@ -676,7 +677,7 @@ _bpftool()
                             ;;
                         ingress|egress|sock_create|sock_ops|device|bind4|bind6|\
                         post_bind4|post_bind6|connect4|connect6|sendmsg4|\
-                        sendmsg6|sysctl)
+                        sendmsg6|recvmsg4|recvmsg6|sysctl)
                             COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
                                 "$cur" ) )
                             return 0
index 7e22f11..73ec8ea 100644 (file)
@@ -25,7 +25,8 @@
        "       ATTACH_TYPE := { ingress | egress | sock_create |\n"           \
        "                        sock_ops | device | bind4 | bind6 |\n"        \
        "                        post_bind4 | post_bind6 | connect4 |\n"       \
-       "                        connect6 | sendmsg4 | sendmsg6 | sysctl }"
+       "                        connect6 | sendmsg4 | sendmsg6 |\n"           \
+       "                        recvmsg4 | recvmsg6 | sysctl }"
 
 static const char * const attach_type_strings[] = {
        [BPF_CGROUP_INET_INGRESS] = "ingress",
@@ -42,6 +43,8 @@ static const char * const attach_type_strings[] = {
        [BPF_CGROUP_UDP4_SENDMSG] = "sendmsg4",
        [BPF_CGROUP_UDP6_SENDMSG] = "sendmsg6",
        [BPF_CGROUP_SYSCTL] = "sysctl",
+       [BPF_CGROUP_UDP4_RECVMSG] = "recvmsg4",
+       [BPF_CGROUP_UDP6_RECVMSG] = "recvmsg6",
        [__MAX_BPF_ATTACH_TYPE] = NULL,
 };
 
index 3ec8290..5da5a73 100644 (file)
@@ -716,12 +716,14 @@ static int dump_map_elem(int fd, void *key, void *value,
                return 0;
 
        if (json_output) {
+               jsonw_start_object(json_wtr);
                jsonw_name(json_wtr, "key");
                print_hex_data_json(key, map_info->key_size);
                jsonw_name(json_wtr, "value");
                jsonw_start_object(json_wtr);
                jsonw_string_field(json_wtr, "error", strerror(lookup_errno));
                jsonw_end_object(json_wtr);
+               jsonw_end_object(json_wtr);
        } else {
                const char *msg = NULL;
 
index 26336ba..7a4e21a 100644 (file)
@@ -1063,7 +1063,8 @@ static int do_help(int argc, char **argv)
                "                 sk_reuseport | flow_dissector | cgroup/sysctl |\n"
                "                 cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n"
                "                 cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n"
-               "                 cgroup/sendmsg4 | cgroup/sendmsg6 }\n"
+               "                 cgroup/sendmsg4 | cgroup/sendmsg6 | cgroup/recvmsg4 |\n"
+               "                 cgroup/recvmsg6 }\n"
                "       ATTACH_TYPE := { msg_verdict | stream_verdict | stream_parser |\n"
                "                        flow_dissector }\n"
                "       " HELP_SPEC_OPTIONS "\n"
index 63e0cf6..e4114a7 100644 (file)
@@ -192,6 +192,8 @@ enum bpf_attach_type {
        BPF_LIRC_MODE2,
        BPF_FLOW_DISSECTOR,
        BPF_CGROUP_SYSCTL,
+       BPF_CGROUP_UDP4_RECVMSG,
+       BPF_CGROUP_UDP6_RECVMSG,
        __MAX_BPF_ATTACH_TYPE
 };
 
index 197b574..151f7ac 100644 (file)
@@ -1645,14 +1645,16 @@ static int bpf_object__probe_btf_func(struct bpf_object *obj)
                /* FUNC x */                                    /* [3] */
                BTF_TYPE_ENC(5, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 0), 2),
        };
-       int res;
+       int btf_fd;
 
-       res = libbpf__probe_raw_btf((char *)types, sizeof(types),
-                                   strs, sizeof(strs));
-       if (res < 0)
-               return res;
-       if (res > 0)
+       btf_fd = libbpf__load_raw_btf((char *)types, sizeof(types),
+                                     strs, sizeof(strs));
+       if (btf_fd >= 0) {
                obj->caps.btf_func = 1;
+               close(btf_fd);
+               return 1;
+       }
+
        return 0;
 }
 
@@ -1670,14 +1672,16 @@ static int bpf_object__probe_btf_datasec(struct bpf_object *obj)
                BTF_TYPE_ENC(3, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
                BTF_VAR_SECINFO_ENC(2, 0, 4),
        };
-       int res;
+       int btf_fd;
 
-       res = libbpf__probe_raw_btf((char *)types, sizeof(types),
-                                   strs, sizeof(strs));
-       if (res < 0)
-               return res;
-       if (res > 0)
+       btf_fd = libbpf__load_raw_btf((char *)types, sizeof(types),
+                                     strs, sizeof(strs));
+       if (btf_fd >= 0) {
                obj->caps.btf_datasec = 1;
+               close(btf_fd);
+               return 1;
+       }
+
        return 0;
 }
 
@@ -3206,6 +3210,10 @@ static const struct {
                                                BPF_CGROUP_UDP4_SENDMSG),
        BPF_EAPROG_SEC("cgroup/sendmsg6",       BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
                                                BPF_CGROUP_UDP6_SENDMSG),
+       BPF_EAPROG_SEC("cgroup/recvmsg4",       BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
+                                               BPF_CGROUP_UDP4_RECVMSG),
+       BPF_EAPROG_SEC("cgroup/recvmsg6",       BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
+                                               BPF_CGROUP_UDP6_RECVMSG),
        BPF_EAPROG_SEC("cgroup/sysctl",         BPF_PROG_TYPE_CGROUP_SYSCTL,
                                                BPF_CGROUP_SYSCTL),
 };
index f3025b4..dfab801 100644 (file)
@@ -34,7 +34,7 @@ do {                          \
 #define pr_info(fmt, ...)      __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
 #define pr_debug(fmt, ...)     __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)
 
-int libbpf__probe_raw_btf(const char *raw_types, size_t types_len,
-                         const char *str_sec, size_t str_len);
+int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
+                        const char *str_sec, size_t str_len);
 
 #endif /* __LIBBPF_LIBBPF_INTERNAL_H */
index 5e2aa83..6635a31 100644 (file)
@@ -133,8 +133,8 @@ bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex)
        return errno != EINVAL && errno != EOPNOTSUPP;
 }
 
-int libbpf__probe_raw_btf(const char *raw_types, size_t types_len,
-                         const char *str_sec, size_t str_len)
+int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
+                        const char *str_sec, size_t str_len)
 {
        struct btf_header hdr = {
                .magic = BTF_MAGIC,
@@ -157,14 +157,9 @@ int libbpf__probe_raw_btf(const char *raw_types, size_t types_len,
        memcpy(raw_btf + hdr.hdr_len + hdr.type_len, str_sec, hdr.str_len);
 
        btf_fd = bpf_load_btf(raw_btf, btf_len, NULL, 0, false);
-       if (btf_fd < 0) {
-               free(raw_btf);
-               return 0;
-       }
 
-       close(btf_fd);
        free(raw_btf);
-       return 1;
+       return btf_fd;
 }
 
 static int load_sk_storage_btf(void)
@@ -190,7 +185,7 @@ static int load_sk_storage_btf(void)
                BTF_MEMBER_ENC(23, 2, 32),/* struct bpf_spin_lock l; */
        };
 
-       return libbpf__probe_raw_btf((char *)types, sizeof(types),
+       return libbpf__load_raw_btf((char *)types, sizeof(types),
                                     strs, sizeof(strs));
 }
 
index 66f2dca..e36356e 100644 (file)
@@ -21,8 +21,8 @@ LDLIBS += -lcap -lelf -lrt -lpthread
 # Order correspond to 'make run_tests' order
 TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
        test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \
-       test_sock test_btf test_sockmap test_lirc_mode2_user get_cgroup_id_user \
-       test_socket_cookie test_cgroup_storage test_select_reuseport test_section_names \
+       test_sock test_btf test_sockmap get_cgroup_id_user test_socket_cookie \
+       test_cgroup_storage test_select_reuseport test_section_names \
        test_netcnt test_tcpnotify_user test_sock_fields test_sysctl
 
 BPF_OBJ_FILES = $(patsubst %.c,%.o, $(notdir $(wildcard progs/*.c)))
@@ -63,7 +63,8 @@ TEST_PROGS_EXTENDED := with_addr.sh \
 
 # Compile but not part of 'make run_tests'
 TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr test_skb_cgroup_id_user \
-       flow_dissector_load test_flow_dissector test_tcp_check_syncookie_user
+       flow_dissector_load test_flow_dissector test_tcp_check_syncookie_user \
+       test_lirc_mode2_user
 
 include ../lib.mk
 
index fbd1d88..c938283 100644 (file)
@@ -3,6 +3,7 @@
 #include <error.h>
 #include <linux/if.h>
 #include <linux/if_tun.h>
+#include <sys/uio.h>
 
 #define CHECK_FLOW_KEYS(desc, got, expected)                           \
        CHECK_ATTR(memcmp(&got, &expected, sizeof(got)) != 0,           \
index bebd4fb..dee2f2e 100644 (file)
@@ -119,6 +119,16 @@ static struct sec_name_test tests[] = {
                {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG},
                {0, BPF_CGROUP_UDP6_SENDMSG},
        },
+       {
+               "cgroup/recvmsg4",
+               {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_RECVMSG},
+               {0, BPF_CGROUP_UDP4_RECVMSG},
+       },
+       {
+               "cgroup/recvmsg6",
+               {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_RECVMSG},
+               {0, BPF_CGROUP_UDP6_RECVMSG},
+       },
        {
                "cgroup/sysctl",
                {0, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL},
index 3f110ea..4ecde23 100644 (file)
@@ -76,6 +76,7 @@ struct sock_addr_test {
        enum {
                LOAD_REJECT,
                ATTACH_REJECT,
+               ATTACH_OKAY,
                SYSCALL_EPERM,
                SYSCALL_ENOTSUPP,
                SUCCESS,
@@ -88,9 +89,13 @@ static int connect4_prog_load(const struct sock_addr_test *test);
 static int connect6_prog_load(const struct sock_addr_test *test);
 static int sendmsg_allow_prog_load(const struct sock_addr_test *test);
 static int sendmsg_deny_prog_load(const struct sock_addr_test *test);
+static int recvmsg_allow_prog_load(const struct sock_addr_test *test);
+static int recvmsg_deny_prog_load(const struct sock_addr_test *test);
 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
+static int recvmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
 static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
+static int recvmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test);
@@ -507,6 +512,92 @@ static struct sock_addr_test tests[] = {
                SRC6_REWRITE_IP,
                SYSCALL_EPERM,
        },
+
+       /* recvmsg */
+       {
+               "recvmsg4: return code ok",
+               recvmsg_allow_prog_load,
+               BPF_CGROUP_UDP4_RECVMSG,
+               BPF_CGROUP_UDP4_RECVMSG,
+               AF_INET,
+               SOCK_DGRAM,
+               NULL,
+               0,
+               NULL,
+               0,
+               NULL,
+               ATTACH_OKAY,
+       },
+       {
+               "recvmsg4: return code !ok",
+               recvmsg_deny_prog_load,
+               BPF_CGROUP_UDP4_RECVMSG,
+               BPF_CGROUP_UDP4_RECVMSG,
+               AF_INET,
+               SOCK_DGRAM,
+               NULL,
+               0,
+               NULL,
+               0,
+               NULL,
+               LOAD_REJECT,
+       },
+       {
+               "recvmsg6: return code ok",
+               recvmsg_allow_prog_load,
+               BPF_CGROUP_UDP6_RECVMSG,
+               BPF_CGROUP_UDP6_RECVMSG,
+               AF_INET6,
+               SOCK_DGRAM,
+               NULL,
+               0,
+               NULL,
+               0,
+               NULL,
+               ATTACH_OKAY,
+       },
+       {
+               "recvmsg6: return code !ok",
+               recvmsg_deny_prog_load,
+               BPF_CGROUP_UDP6_RECVMSG,
+               BPF_CGROUP_UDP6_RECVMSG,
+               AF_INET6,
+               SOCK_DGRAM,
+               NULL,
+               0,
+               NULL,
+               0,
+               NULL,
+               LOAD_REJECT,
+       },
+       {
+               "recvmsg4: rewrite IP & port (asm)",
+               recvmsg4_rw_asm_prog_load,
+               BPF_CGROUP_UDP4_RECVMSG,
+               BPF_CGROUP_UDP4_RECVMSG,
+               AF_INET,
+               SOCK_DGRAM,
+               SERV4_REWRITE_IP,
+               SERV4_REWRITE_PORT,
+               SERV4_REWRITE_IP,
+               SERV4_REWRITE_PORT,
+               SERV4_IP,
+               SUCCESS,
+       },
+       {
+               "recvmsg6: rewrite IP & port (asm)",
+               recvmsg6_rw_asm_prog_load,
+               BPF_CGROUP_UDP6_RECVMSG,
+               BPF_CGROUP_UDP6_RECVMSG,
+               AF_INET6,
+               SOCK_DGRAM,
+               SERV6_REWRITE_IP,
+               SERV6_REWRITE_PORT,
+               SERV6_REWRITE_IP,
+               SERV6_REWRITE_PORT,
+               SERV6_IP,
+               SUCCESS,
+       },
 };
 
 static int mk_sockaddr(int domain, const char *ip, unsigned short port,
@@ -765,8 +856,8 @@ static int connect6_prog_load(const struct sock_addr_test *test)
        return load_path(test, CONNECT6_PROG_PATH);
 }
 
-static int sendmsg_ret_only_prog_load(const struct sock_addr_test *test,
-                                     int32_t rc)
+static int xmsg_ret_only_prog_load(const struct sock_addr_test *test,
+                                  int32_t rc)
 {
        struct bpf_insn insns[] = {
                /* return rc */
@@ -778,12 +869,22 @@ static int sendmsg_ret_only_prog_load(const struct sock_addr_test *test,
 
 static int sendmsg_allow_prog_load(const struct sock_addr_test *test)
 {
-       return sendmsg_ret_only_prog_load(test, /*rc*/ 1);
+       return xmsg_ret_only_prog_load(test, /*rc*/ 1);
 }
 
 static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
 {
-       return sendmsg_ret_only_prog_load(test, /*rc*/ 0);
+       return xmsg_ret_only_prog_load(test, /*rc*/ 0);
+}
+
+static int recvmsg_allow_prog_load(const struct sock_addr_test *test)
+{
+       return xmsg_ret_only_prog_load(test, /*rc*/ 1);
+}
+
+static int recvmsg_deny_prog_load(const struct sock_addr_test *test)
+{
+       return xmsg_ret_only_prog_load(test, /*rc*/ 0);
 }
 
 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
@@ -838,6 +939,47 @@ static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
        return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
 }
 
+static int recvmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
+{
+       struct sockaddr_in src4_rw_addr;
+
+       if (mk_sockaddr(AF_INET, SERV4_IP, SERV4_PORT,
+                       (struct sockaddr *)&src4_rw_addr,
+                       sizeof(src4_rw_addr)) == -1)
+               return -1;
+
+       struct bpf_insn insns[] = {
+               BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+
+               /* if (sk.family == AF_INET && */
+               BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
+                           offsetof(struct bpf_sock_addr, family)),
+               BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 6),
+
+               /*     sk.type == SOCK_DGRAM)  { */
+               BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
+                           offsetof(struct bpf_sock_addr, type)),
+               BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 4),
+
+               /*      user_ip4 = src4_rw_addr.sin_addr */
+               BPF_MOV32_IMM(BPF_REG_7, src4_rw_addr.sin_addr.s_addr),
+               BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
+                           offsetof(struct bpf_sock_addr, user_ip4)),
+
+               /*      user_port = src4_rw_addr.sin_port */
+               BPF_MOV32_IMM(BPF_REG_7, src4_rw_addr.sin_port),
+               BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
+                           offsetof(struct bpf_sock_addr, user_port)),
+               /* } */
+
+               /* return 1 */
+               BPF_MOV64_IMM(BPF_REG_0, 1),
+               BPF_EXIT_INSN(),
+       };
+
+       return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
+}
+
 static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test)
 {
        return load_path(test, SENDMSG4_PROG_PATH);
@@ -901,6 +1043,39 @@ static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test)
        return sendmsg6_rw_dst_asm_prog_load(test, SERV6_REWRITE_IP);
 }
 
+static int recvmsg6_rw_asm_prog_load(const struct sock_addr_test *test)
+{
+       struct sockaddr_in6 src6_rw_addr;
+
+       if (mk_sockaddr(AF_INET6, SERV6_IP, SERV6_PORT,
+                       (struct sockaddr *)&src6_rw_addr,
+                       sizeof(src6_rw_addr)) == -1)
+               return -1;
+
+       struct bpf_insn insns[] = {
+               BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+
+               /* if (sk.family == AF_INET6) { */
+               BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
+                           offsetof(struct bpf_sock_addr, family)),
+               BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 10),
+
+               STORE_IPV6(user_ip6, src6_rw_addr.sin6_addr.s6_addr32),
+
+               /*      user_port = dst6_rw_addr.sin6_port */
+               BPF_MOV32_IMM(BPF_REG_7, src6_rw_addr.sin6_port),
+               BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
+                           offsetof(struct bpf_sock_addr, user_port)),
+               /* } */
+
+               /* return 1 */
+               BPF_MOV64_IMM(BPF_REG_0, 1),
+               BPF_EXIT_INSN(),
+       };
+
+       return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
+}
+
 static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test)
 {
        return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP);
@@ -1282,13 +1457,13 @@ out:
        return err;
 }
 
-static int run_sendmsg_test_case(const struct sock_addr_test *test)
+static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
 {
        socklen_t addr_len = sizeof(struct sockaddr_storage);
-       struct sockaddr_storage expected_src_addr;
-       struct sockaddr_storage requested_addr;
        struct sockaddr_storage expected_addr;
-       struct sockaddr_storage real_src_addr;
+       struct sockaddr_storage server_addr;
+       struct sockaddr_storage sendmsg_addr;
+       struct sockaddr_storage recvmsg_addr;
        int clientfd = -1;
        int servfd = -1;
        int set_cmsg;
@@ -1297,20 +1472,19 @@ static int run_sendmsg_test_case(const struct sock_addr_test *test)
        if (test->type != SOCK_DGRAM)
                goto err;
 
-       if (init_addrs(test, &requested_addr, &expected_addr,
-                      &expected_src_addr))
+       if (init_addrs(test, &sendmsg_addr, &server_addr, &expected_addr))
                goto err;
 
        /* Prepare server to sendmsg to */
-       servfd = start_server(test->type, &expected_addr, addr_len);
+       servfd = start_server(test->type, &server_addr, addr_len);
        if (servfd == -1)
                goto err;
 
-       for (set_cmsg = 0; set_cmsg <= 1; ++set_cmsg) {
+       for (set_cmsg = 0; set_cmsg <= max_cmsg; ++set_cmsg) {
                if (clientfd >= 0)
                        close(clientfd);
 
-               clientfd = sendmsg_to_server(test->type, &requested_addr,
+               clientfd = sendmsg_to_server(test->type, &sendmsg_addr,
                                             addr_len, set_cmsg, /*flags*/0,
                                             &err);
                if (err)
@@ -1330,10 +1504,10 @@ static int run_sendmsg_test_case(const struct sock_addr_test *test)
                 * specific packet may differ from the one used by default and
                 * returned by getsockname(2).
                 */
-               if (recvmsg_from_client(servfd, &real_src_addr) == -1)
+               if (recvmsg_from_client(servfd, &recvmsg_addr) == -1)
                        goto err;
 
-               if (cmp_addr(&real_src_addr, &expected_src_addr, /*cmp_port*/0))
+               if (cmp_addr(&recvmsg_addr, &expected_addr, /*cmp_port*/0))
                        goto err;
        }
 
@@ -1366,6 +1540,9 @@ static int run_test_case(int cgfd, const struct sock_addr_test *test)
                goto out;
        } else if (test->expected_result == ATTACH_REJECT || err) {
                goto err;
+       } else if (test->expected_result == ATTACH_OKAY) {
+               err = 0;
+               goto out;
        }
 
        switch (test->attach_type) {
@@ -1379,7 +1556,11 @@ static int run_test_case(int cgfd, const struct sock_addr_test *test)
                break;
        case BPF_CGROUP_UDP4_SENDMSG:
        case BPF_CGROUP_UDP6_SENDMSG:
-               err = run_sendmsg_test_case(test);
+               err = run_xmsg_test_case(test, 1);
+               break;
+       case BPF_CGROUP_UDP4_RECVMSG:
+       case BPF_CGROUP_UDP6_RECVMSG:
+               err = run_xmsg_test_case(test, 0);
                break;
        default:
                goto err;
diff --git a/tools/testing/selftests/bpf/verifier/subreg.c b/tools/testing/selftests/bpf/verifier/subreg.c
new file mode 100644 (file)
index 0000000..4c4133c
--- /dev/null
@@ -0,0 +1,533 @@
+/* This file contains sub-register zero extension checks for insns defining
+ * sub-registers, meaning:
+ *   - All insns under BPF_ALU class. Their BPF_ALU32 variants or narrow width
+ *     forms (BPF_END) could define sub-registers.
+ *   - Narrow direct loads, BPF_B/H/W | BPF_LDX.
+ *   - BPF_LD is not exposed to JIT back-ends, so no need for testing.
+ *
+ * "get_prandom_u32" is used to initialize low 32-bit of some registers to
+ * prevent potential optimizations done by verifier or JIT back-ends which could
+ * optimize register back into constant when range info shows one register is a
+ * constant.
+ */
+{
+       "add32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x100000000ULL),
+       BPF_ALU32_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "add32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       /* An insn could have no effect on the low 32-bit, for example:
+        *   a = a + 0
+        *   a = a | 0
+        *   a = a & -1
+        * But, they should still zero high 32-bit.
+        */
+       BPF_ALU32_IMM(BPF_ADD, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_ADD, BPF_REG_0, -2),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "sub32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x1ffffffffULL),
+       BPF_ALU32_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "sub32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_SUB, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_SUB, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "mul32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x100000001ULL),
+       BPF_ALU32_REG(BPF_MUL, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "mul32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_MUL, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_MUL, BPF_REG_0, -1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "div32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_MOV64_IMM(BPF_REG_0, -1),
+       BPF_ALU32_REG(BPF_DIV, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "div32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_DIV, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_DIV, BPF_REG_0, 2),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "or32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x100000001ULL),
+       BPF_ALU32_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "or32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_OR, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_OR, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "and32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x100000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x1ffffffffULL),
+       BPF_ALU32_REG(BPF_AND, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "and32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_AND, BPF_REG_0, -1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_AND, BPF_REG_0, -2),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "lsh32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x100000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_MOV64_IMM(BPF_REG_1, 1),
+       BPF_ALU32_REG(BPF_LSH, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "lsh32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_LSH, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_LSH, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "rsh32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_MOV64_IMM(BPF_REG_1, 1),
+       BPF_ALU32_REG(BPF_RSH, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "rsh32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_RSH, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_RSH, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "neg32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_NEG, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "mod32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_MOV64_IMM(BPF_REG_0, -1),
+       BPF_ALU32_REG(BPF_MOD, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "mod32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_MOD, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_MOD, BPF_REG_0, 2),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "xor32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x100000000ULL),
+       BPF_ALU32_REG(BPF_XOR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "xor32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_XOR, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "mov32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x100000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x100000000ULL),
+       BPF_MOV32_REG(BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "mov32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_MOV32_IMM(BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_MOV32_IMM(BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "arsh32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_MOV64_IMM(BPF_REG_1, 1),
+       BPF_ALU32_REG(BPF_ARSH, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "arsh32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_ARSH, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_ARSH, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "end16 (to_le) reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 32),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_ENDIAN(BPF_TO_LE, BPF_REG_0, 16),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "end32 (to_le) reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 32),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_ENDIAN(BPF_TO_LE, BPF_REG_0, 32),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "end16 (to_be) reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 32),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_ENDIAN(BPF_TO_BE, BPF_REG_0, 16),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "end32 (to_be) reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 32),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_ENDIAN(BPF_TO_BE, BPF_REG_0, 32),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "ldx_b zero extend check",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -4),
+       BPF_ST_MEM(BPF_W, BPF_REG_6, 0, 0xfaceb00c),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_6, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "ldx_h zero extend check",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -4),
+       BPF_ST_MEM(BPF_W, BPF_REG_6, 0, 0xfaceb00c),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_6, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "ldx_w zero extend check",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -4),
+       BPF_ST_MEM(BPF_W, BPF_REG_6, 0, 0xfaceb00c),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
index be59f9c..79053a4 100644 (file)
@@ -198,7 +198,7 @@ static int test_cgcore_no_internal_process_constraint_on_threads(const char *roo
        char *parent = NULL, *child = NULL;
 
        if (cg_read_strstr(root, "cgroup.controllers", "cpu") ||
-           cg_read_strstr(root, "cgroup.subtree_control", "cpu")) {
+           cg_write(root, "cgroup.subtree_control", "+cpu")) {
                ret = KSFT_SKIP;
                goto cleanup;
        }
@@ -376,6 +376,11 @@ int main(int argc, char *argv[])
 
        if (cg_find_unified_root(root, sizeof(root)))
                ksft_exit_skip("cgroup v2 isn't mounted\n");
+
+       if (cg_read_strstr(root, "cgroup.subtree_control", "memory"))
+               if (cg_write(root, "cgroup.subtree_control", "+memory"))
+                       ksft_exit_skip("Failed to set memory controller\n");
+
        for (i = 0; i < ARRAY_SIZE(tests); i++) {
                switch (tests[i].fn(root)) {
                case KSFT_PASS:
index 6f33988..c19a97d 100644 (file)
@@ -1205,6 +1205,10 @@ int main(int argc, char **argv)
        if (cg_read_strstr(root, "cgroup.controllers", "memory"))
                ksft_exit_skip("memory controller isn't available\n");
 
+       if (cg_read_strstr(root, "cgroup.subtree_control", "memory"))
+               if (cg_write(root, "cgroup.subtree_control", "+memory"))
+                       ksft_exit_skip("Failed to set memory controller\n");
+
        for (i = 0; i < ARRAY_SIZE(tests); i++) {
                switch (tests[i].fn(root)) {
                case KSFT_PASS:
index 9a678ec..4eac0a0 100755 (executable)
@@ -145,16 +145,19 @@ bc_forwarding_disable()
 {
        sysctl_set net.ipv4.conf.all.bc_forwarding 0
        sysctl_set net.ipv4.conf.$rp1.bc_forwarding 0
+       sysctl_set net.ipv4.conf.$rp2.bc_forwarding 0
 }
 
 bc_forwarding_enable()
 {
        sysctl_set net.ipv4.conf.all.bc_forwarding 1
        sysctl_set net.ipv4.conf.$rp1.bc_forwarding 1
+       sysctl_set net.ipv4.conf.$rp2.bc_forwarding 1
 }
 
 bc_forwarding_restore()
 {
+       sysctl_restore net.ipv4.conf.$rp2.bc_forwarding
        sysctl_restore net.ipv4.conf.$rp1.bc_forwarding
        sysctl_restore net.ipv4.conf.all.bc_forwarding
 }
@@ -171,7 +174,7 @@ ping_test_from()
        log_info "ping $dip, expected reply from $from"
        ip vrf exec $(master_name_get $oif) \
                $PING -I $oif $dip -c 10 -i 0.1 -w $PING_TIMEOUT -b 2>&1 \
-               | grep $from &> /dev/null
+               | grep "bytes from $from" > /dev/null
        check_err_fail $fail $?
 }
 
index 5bae179..104c75a 100644 (file)
 
 #include "../kselftest.h"
 
+#ifndef __NR_pidfd_send_signal
+#define __NR_pidfd_send_signal -1
+#endif
+
 static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
                                        unsigned int flags)
 {
index e13eb6c..05306c5 100644 (file)
@@ -25,6 +25,8 @@ TEST_GEN_FILES += virtual_address_range
 
 TEST_PROGS := run_vmtests
 
+TEST_FILES := test_vmalloc.sh
+
 KSFT_KHDR_INSTALL := 1
 include ../lib.mk
 
index 5d1db82..b3e6497 100644 (file)
@@ -123,7 +123,7 @@ static void usage(void)
        fprintf(stderr, "Supported <test type>: anon, hugetlb, "
                "hugetlb_shared, shmem\n\n");
        fprintf(stderr, "Examples:\n\n");
-       fprintf(stderr, examples);
+       fprintf(stderr, "%s", examples);
        exit(1);
 }
 
index 7ef45a4..6683b4a 100644 (file)
@@ -127,7 +127,7 @@ static inline void free_page(unsigned long addr)
 #define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
 #define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
 
-#define WARN_ON_ONCE(cond) ((cond) ? fprintf (stderr, "WARNING\n") : 0)
+#define WARN_ON_ONCE(cond) (unlikely(cond) ? fprintf (stderr, "WARNING\n") : 0)
 
 #define min(x, y) ({                           \
        typeof(x) _min1 = (x);                  \