Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Jun 2016 17:37:01 +0000 (10:37 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Jun 2016 17:37:01 +0000 (10:37 -0700)
Pull objtool fix from Ingo Molnar:
 "Addresses a false positive warning in the GPU/DRM code"

[ Technically it's not a "false positive", but it's the virtual GPU
  interface that needs the frame pointer for its own internal purposes ]

* 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  objtool, drm/vmwgfx: Fix "duplicate frame pointer save" warning

231 files changed:
MAINTAINERS
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/boot/dts/abilis_tb100.dtsi
arch/arc/boot/dts/abilis_tb101.dtsi
arch/arc/boot/dts/axc001.dtsi
arch/arc/boot/dts/axc003.dtsi
arch/arc/boot/dts/axc003_idu.dtsi
arch/arc/boot/dts/eznps.dts
arch/arc/boot/dts/nsim_700.dts
arch/arc/boot/dts/nsimosci.dts
arch/arc/boot/dts/nsimosci_hs.dts
arch/arc/boot/dts/nsimosci_hs_idu.dts
arch/arc/boot/dts/skeleton.dtsi
arch/arc/boot/dts/skeleton_hs.dtsi
arch/arc/boot/dts/skeleton_hs_idu.dtsi
arch/arc/boot/dts/vdk_axc003.dtsi
arch/arc/boot/dts/vdk_axc003_idu.dtsi
arch/arc/include/asm/atomic.h
arch/arc/include/asm/entry-compact.h
arch/arc/include/asm/mmu_context.h
arch/arc/include/asm/pgtable.h
arch/arc/include/asm/processor.h
arch/arc/include/asm/smp.h
arch/arc/include/asm/spinlock.h
arch/arc/include/asm/thread_info.h
arch/arc/include/asm/uaccess.h
arch/arc/include/uapi/asm/swab.h
arch/arc/kernel/entry-compact.S
arch/arc/kernel/intc-compact.c
arch/arc/kernel/perf_event.c
arch/arc/kernel/setup.c
arch/arc/kernel/signal.c
arch/arc/kernel/troubleshoot.c
arch/arc/mm/cache.c
arch/arc/mm/dma.c
drivers/acpi/bus.c
drivers/acpi/ec.c
drivers/acpi/internal.h
drivers/cpufreq/intel_pstate.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/ci_dpm.c
drivers/gpu/drm/amd/amdgpu/cik_sdma.c
drivers/gpu/drm/amd/amdgpu/fiji_dpm.c
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/iceland_dpm.c
drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
drivers/gpu/drm/amd/amdgpu/tonga_dpm.c
drivers/gpu/drm/amd/include/amd_shared.h
drivers/gpu/drm/amd/include/cgs_common.h
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c
drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c
drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/msm_fbdev.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/msm/msm_rd.c
drivers/gpu/drm/msm/msm_ringbuffer.c
drivers/gpu/drm/nouveau/include/nvkm/core/device.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/disp.h
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nv04_fbcon.c
drivers/gpu/drm/nouveau/nv50_fbcon.c
drivers/gpu/drm/nouveau/nvc0_fbcon.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/disp.c
drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c
drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c
drivers/gpu/drm/omapdrm/dss/dsi.c
drivers/gpu/drm/omapdrm/dss/hdmi5.c
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_drv.c
drivers/gpu/drm/vc4/vc4_kms.c
drivers/gpu/drm/vc4/vc4_regs.h
drivers/infiniband/core/cache.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/device.c
drivers/infiniband/core/iwpm_msg.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/sysfs.c
drivers/infiniband/hw/hfi1/affinity.c
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/init.c
drivers/infiniband/hw/hfi1/trace.c
drivers/infiniband/hw/hfi1/user_sdma.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx5/cq.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/usnic/usnic_uiom.c
drivers/infiniband/sw/rdmavt/qp.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/ipoib/ipoib_vlan.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
drivers/net/ethernet/ethoc.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/qp.c
drivers/net/ethernet/mellanox/mlx5/core/vport.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qed/qed_sriov.h
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/sfc/mcdi_port.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vmxnet3/vmxnet3_int.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/realtek/rtlwifi/core.c
include/linux/cpuidle.h
include/linux/mlx5/device.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mlx5/qp.h
include/linux/mlx5/vport.h
include/net/compat.h
include/net/ip_vs.h
include/net/netfilter/nf_queue.h
include/net/netns/netfilter.h
include/net/pkt_cls.h
include/net/sch_generic.h
include/rdma/ib_verbs.h
include/uapi/linux/gtp.h
include/uapi/sound/Kbuild
kernel/relay.c
kernel/sched/idle.c
kernel/trace/bpf_trace.c
mm/fadvise.c
mm/hugetlb.c
mm/kasan/kasan.c
mm/memcontrol.c
mm/swap.c
mm/swap_state.c
net/bridge/br_fdb.c
net/compat.c
net/core/gen_stats.c
net/core/net-sysfs.c
net/ipv4/udp.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/ipv6/netfilter/nf_dup_ipv6.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/l2tp/l2tp_core.c
net/mac80211/mesh.c
net/mac80211/sta_info.h
net/netfilter/ipvs/ip_vs_conn.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/nf_conntrack_ftp.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_irc.c
net/netfilter/nf_conntrack_sane.c
net/netfilter/nf_conntrack_sip.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_conntrack_tftp.c
net/netfilter/nf_queue.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_queue.c
net/netfilter/x_tables.c
net/packet/af_packet.c
net/rds/rds.h
net/rds/recv.c
net/rds/send.c
net/rds/tcp.c
net/rds/tcp.h
net/rds/tcp_connect.c
net/rds/tcp_listen.c
net/rds/threads.c
net/rxrpc/rxkad.c
net/sched/act_police.c
net/sched/cls_flower.c
net/sched/cls_u32.c
net/sched/sch_drr.c
net/sched/sch_fq_codel.c
net/sched/sch_generic.c
net/sched/sch_hfsc.c
net/sched/sch_ingress.c
net/sched/sch_prio.c
net/sched/sch_qfq.c
net/sched/sch_red.c
net/sched/sch_tbf.c
net/tipc/netlink_compat.c
net/wireless/core.c
net/wireless/wext-core.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
tools/testing/selftests/net/reuseport_bpf.c

index 66de4da..2ebe195 100644 (file)
@@ -8009,6 +8009,7 @@ Q:        http://patchwork.kernel.org/project/linux-wireless/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git
 S:     Maintained
+F:     Documentation/devicetree/bindings/net/wireless/
 F:     drivers/net/wireless/
 
 NETXEN (1/10) GbE SUPPORT
index 0dcbacf..0d3e59f 100644 (file)
@@ -61,7 +61,7 @@ config RWSEM_GENERIC_SPINLOCK
        def_bool y
 
 config ARCH_DISCONTIGMEM_ENABLE
-       def_bool y
+       def_bool n
 
 config ARCH_FLATMEM_ENABLE
        def_bool y
@@ -186,9 +186,6 @@ if SMP
 config ARC_HAS_COH_CACHES
        def_bool n
 
-config ARC_HAS_REENTRANT_IRQ_LV2
-       def_bool n
-
 config ARC_MCIP
        bool "ARConnect Multicore IP (MCIP) Support "
        depends on ISA_ARCV2
@@ -366,25 +363,10 @@ config NODES_SHIFT
 if ISA_ARCOMPACT
 
 config ARC_COMPACT_IRQ_LEVELS
-       bool "ARCompact IRQ Priorities: High(2)/Low(1)"
+       bool "Setup Timer IRQ as high Priority"
        default n
-       # Timer HAS to be high priority, for any other high priority config
-       select ARC_IRQ3_LV2
        # if SMP, LV2 enabled ONLY if ARC implementation has LV2 re-entrancy
-       depends on !SMP || ARC_HAS_REENTRANT_IRQ_LV2
-
-if ARC_COMPACT_IRQ_LEVELS
-
-config ARC_IRQ3_LV2
-       bool
-
-config ARC_IRQ5_LV2
-       bool
-
-config ARC_IRQ6_LV2
-       bool
-
-endif  #ARC_COMPACT_IRQ_LEVELS
+       depends on !SMP
 
 config ARC_FPU_SAVE_RESTORE
        bool "Enable FPU state persistence across context switch"
@@ -407,11 +389,6 @@ config ARC_HAS_LLSC
        default y
        depends on !ARC_CANT_LLSC
 
-config ARC_STAR_9000923308
-       bool "Workaround for llock/scond livelock"
-       default n
-       depends on ISA_ARCV2 && SMP && ARC_HAS_LLSC
-
 config ARC_HAS_SWAPE
        bool "Insn: SWAPE (endian-swap)"
        default y
@@ -471,7 +448,7 @@ config LINUX_LINK_BASE
 
 config HIGHMEM
        bool "High Memory Support"
-       select DISCONTIGMEM
+       select ARCH_DISCONTIGMEM_ENABLE
        help
          With ARC 2G:2G address split, only upper 2G is directly addressable by
          kernel. Enable this to potentially allow access to rest of 2G and PAE
index 02fabef..d4df6be 100644 (file)
@@ -127,7 +127,7 @@ libs-y              += arch/arc/lib/ $(LIBGCC)
 
 boot           := arch/arc/boot
 
-#default target for make without any arguements.
+#default target for make without any arguments.
 KBUILD_IMAGE   := bootpImage
 
 all:   $(KBUILD_IMAGE)
index 3942634..02410b2 100644 (file)
@@ -23,8 +23,6 @@
 
 
 / {
-       clock-frequency         = <500000000>;  /* 500 MHZ */
-
        soc100 {
                bus-frequency   = <166666666>;
 
index b046722..f9e7686 100644 (file)
@@ -23,8 +23,6 @@
 
 
 / {
-       clock-frequency         = <500000000>;  /* 500 MHZ */
-
        soc100 {
                bus-frequency   = <166666666>;
 
index 3e02f15..6ae2c47 100644 (file)
@@ -15,7 +15,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <750000000>;  /* 750 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
 
index 378e455..14df46f 100644 (file)
@@ -14,7 +14,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <90000000>;
        #address-cells = <1>;
        #size-cells = <1>;
 
index 64c94b2..3d6cfa3 100644 (file)
@@ -14,7 +14,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <90000000>;
        #address-cells = <1>;
        #size-cells = <1>;
 
index b89f6c3..1e0d225 100644 (file)
@@ -18,7 +18,6 @@
 
 / {
        compatible = "ezchip,arc-nps";
-       clock-frequency = <83333333>;   /* 83.333333 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        interrupt-parent = <&intc>;
index 5d5e373..6397051 100644 (file)
@@ -11,7 +11,6 @@
 
 / {
        compatible = "snps,nsim";
-       clock-frequency = <80000000>;   /* 80 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        interrupt-parent = <&core_intc>;
index b5b060a..763d66c 100644 (file)
@@ -11,7 +11,6 @@
 
 / {
        compatible = "snps,nsimosci";
-       clock-frequency = <20000000>;   /* 20 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        interrupt-parent = <&core_intc>;
index 325e730..4eb97c5 100644 (file)
@@ -11,7 +11,6 @@
 
 / {
        compatible = "snps,nsimosci_hs";
-       clock-frequency = <20000000>;   /* 20 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        interrupt-parent = <&core_intc>;
index ee03d71..853f897 100644 (file)
@@ -11,7 +11,6 @@
 
 / {
        compatible = "snps,nsimosci_hs";
-       clock-frequency = <5000000>;    /* 5 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        interrupt-parent = <&core_intc>;
index 3a10cc6..65808fe 100644 (file)
@@ -13,7 +13,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <80000000>;   /* 80 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        chosen { };
index 71fd308..2dfe803 100644 (file)
@@ -8,7 +8,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <80000000>;   /* 80 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        chosen { };
index d1cb25a..4c11079 100644 (file)
@@ -8,7 +8,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <80000000>;   /* 80 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        chosen { };
index ad4ee43..0fd6ba9 100644 (file)
@@ -14,7 +14,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <50000000>;
        #address-cells = <1>;
        #size-cells = <1>;
 
index a3cb626..82214cd 100644 (file)
@@ -15,7 +15,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <50000000>;
        #address-cells = <1>;
        #size-cells = <1>;
 
index 5f3dcbb..dd68399 100644 (file)
 
 #define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
 
-#ifdef CONFIG_ARC_STAR_9000923308
-
-#define SCOND_FAIL_RETRY_VAR_DEF                                               \
-       unsigned int delay = 1, tmp;                                            \
-
-#define SCOND_FAIL_RETRY_ASM                                                   \
-       "       bz      4f                      \n"                             \
-       "   ; --- scond fail delay ---          \n"                             \
-       "       mov     %[tmp], %[delay]        \n"     /* tmp = delay */       \
-       "2:     brne.d  %[tmp], 0, 2b           \n"     /* while (tmp != 0) */  \
-       "       sub     %[tmp], %[tmp], 1       \n"     /* tmp-- */             \
-       "       rol     %[delay], %[delay]      \n"     /* delay *= 2 */        \
-       "       b       1b                      \n"     /* start over */        \
-       "4: ; --- success ---                   \n"                             \
-
-#define SCOND_FAIL_RETRY_VARS                                                  \
-         ,[delay] "+&r" (delay),[tmp] "=&r"    (tmp)                           \
-
-#else  /* !CONFIG_ARC_STAR_9000923308 */
-
-#define SCOND_FAIL_RETRY_VAR_DEF
-
-#define SCOND_FAIL_RETRY_ASM                                                   \
-       "       bnz     1b                      \n"                             \
-
-#define SCOND_FAIL_RETRY_VARS
-
-#endif
-
 #define ATOMIC_OP(op, c_op, asm_op)                                    \
 static inline void atomic_##op(int i, atomic_t *v)                     \
 {                                                                      \
-       unsigned int val;                                               \
-       SCOND_FAIL_RETRY_VAR_DEF                                        \
+       unsigned int val;                                               \
                                                                        \
        __asm__ __volatile__(                                           \
        "1:     llock   %[val], [%[ctr]]                \n"             \
        "       " #asm_op " %[val], %[val], %[i]        \n"             \
        "       scond   %[val], [%[ctr]]                \n"             \
-       "                                               \n"             \
-       SCOND_FAIL_RETRY_ASM                                            \
-                                                                       \
+       "       bnz     1b                              \n"             \
        : [val] "=&r"   (val) /* Early clobber to prevent reg reuse */  \
-         SCOND_FAIL_RETRY_VARS                                         \
        : [ctr] "r"     (&v->counter), /* Not "m": llock only supports reg direct addr mode */  \
          [i]   "ir"    (i)                                             \
        : "cc");                                                        \
@@ -77,8 +44,7 @@ static inline void atomic_##op(int i, atomic_t *v)                    \
 #define ATOMIC_OP_RETURN(op, c_op, asm_op)                             \
 static inline int atomic_##op##_return(int i, atomic_t *v)             \
 {                                                                      \
-       unsigned int val;                                               \
-       SCOND_FAIL_RETRY_VAR_DEF                                        \
+       unsigned int val;                                               \
                                                                        \
        /*                                                              \
         * Explicit full memory barrier needed before/after as          \
@@ -90,11 +56,8 @@ static inline int atomic_##op##_return(int i, atomic_t *v)           \
        "1:     llock   %[val], [%[ctr]]                \n"             \
        "       " #asm_op " %[val], %[val], %[i]        \n"             \
        "       scond   %[val], [%[ctr]]                \n"             \
-       "                                               \n"             \
-       SCOND_FAIL_RETRY_ASM                                            \
-                                                                       \
+       "       bnz     1b                              \n"             \
        : [val] "=&r"   (val)                                           \
-         SCOND_FAIL_RETRY_VARS                                         \
        : [ctr] "r"     (&v->counter),                                  \
          [i]   "ir"    (i)                                             \
        : "cc");                                                        \
index e0e1faf..14c310f 100644 (file)
@@ -76,8 +76,8 @@
         * We need to be a bit more cautious here. What if a kernel bug in
         * L1 ISR, caused SP to go whaco (some small value which looks like
         * USER stk) and then we take L2 ISR.
-        * Above brlo alone would treat it as a valid L1-L2 sceanrio
-        * instead of shouting alound
+        * Above brlo alone would treat it as a valid L1-L2 scenario
+        * instead of shouting around
         * The only feasible way is to make sure this L2 happened in
         * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
         * L1 ISR before it switches stack
index 1fd467e..b0b87f2 100644 (file)
@@ -83,7 +83,7 @@ static inline void get_new_mmu_context(struct mm_struct *mm)
                local_flush_tlb_all();
 
                /*
-                * Above checke for rollover of 8 bit ASID in 32 bit container.
+                * Above check for rollover of 8 bit ASID in 32 bit container.
                 * If the container itself wrapped around, set it to a non zero
                 * "generation" to distinguish from no context
                 */
index 034bbdc..858f98e 100644 (file)
@@ -47,7 +47,7 @@
  * Page Tables are purely for Linux VM's consumption and the bits below are
  * suited to that (uniqueness). Hence some are not implemented in the TLB and
  * some have different value in TLB.
- * e.g. MMU v2: K_READ bit is 8 and so is GLOBAL (possible becoz they live in
+ * e.g. MMU v2: K_READ bit is 8 and so is GLOBAL (possible because they live in
  *      seperate PD0 and PD1, which combined forms a translation entry)
  *      while for PTE perspective, they are 8 and 9 respectively
  * with MMU v3: Most bits (except SHARED) represent the exact hardware pos
index f904899..16b630f 100644 (file)
@@ -78,7 +78,7 @@ struct task_struct;
 #define KSTK_ESP(tsk)   (task_pt_regs(tsk)->sp)
 
 /*
- * Where abouts of Task's sp, fp, blink when it was last seen in kernel mode.
+ * Where about of Task's sp, fp, blink when it was last seen in kernel mode.
  * Look in process.c for details of kernel stack layout
  */
 #define TSK_K_ESP(tsk)         (tsk->thread.ksp)
index 9913804..89fdd1b 100644 (file)
@@ -86,7 +86,7 @@ static inline const char *arc_platform_smp_cpuinfo(void)
  * (1) These insn were introduced only in 4.10 release. So for older released
  *     support needed.
  *
- * (2) In a SMP setup, the LLOCK/SCOND atomiticity across CPUs needs to be
+ * (2) In a SMP setup, the LLOCK/SCOND atomicity across CPUs needs to be
  *     gaurantted by the platform (not something which core handles).
  *     Assuming a platform won't, SMP Linux needs to use spinlocks + local IRQ
  *     disabling for atomicity.
index 800e7c4..cded4a9 100644 (file)
 
 #ifdef CONFIG_ARC_HAS_LLSC
 
-/*
- * A normal LLOCK/SCOND based system, w/o need for livelock workaround
- */
-#ifndef CONFIG_ARC_STAR_9000923308
-
 static inline void arch_spin_lock(arch_spinlock_t *lock)
 {
        unsigned int val;
@@ -238,293 +233,6 @@ static inline void arch_write_unlock(arch_rwlock_t *rw)
        smp_mb();
 }
 
-#else  /* CONFIG_ARC_STAR_9000923308 */
-
-/*
- * HS38x4 could get into a LLOCK/SCOND livelock in case of multiple overlapping
- * coherency transactions in the SCU. The exclusive line state keeps rotating
- * among contenting cores leading to a never ending cycle. So break the cycle
- * by deferring the retry of failed exclusive access (SCOND). The actual delay
- * needed is function of number of contending cores as well as the unrelated
- * coherency traffic from other cores. To keep the code simple, start off with
- * small delay of 1 which would suffice most cases and in case of contention
- * double the delay. Eventually the delay is sufficient such that the coherency
- * pipeline is drained, thus a subsequent exclusive access would succeed.
- */
-
-#define SCOND_FAIL_RETRY_VAR_DEF                                               \
-       unsigned int delay, tmp;                                                \
-
-#define SCOND_FAIL_RETRY_ASM                                                   \
-       "   ; --- scond fail delay ---          \n"                             \
-       "       mov     %[tmp], %[delay]        \n"     /* tmp = delay */       \
-       "2:     brne.d  %[tmp], 0, 2b           \n"     /* while (tmp != 0) */  \
-       "       sub     %[tmp], %[tmp], 1       \n"     /* tmp-- */             \
-       "       rol     %[delay], %[delay]      \n"     /* delay *= 2 */        \
-       "       b       1b                      \n"     /* start over */        \
-       "                                       \n"                             \
-       "4: ; --- done ---                      \n"                             \
-
-#define SCOND_FAIL_RETRY_VARS                                                  \
-         ,[delay] "=&r" (delay), [tmp] "=&r"   (tmp)                           \
-
-static inline void arch_spin_lock(arch_spinlock_t *lock)
-{
-       unsigned int val;
-       SCOND_FAIL_RETRY_VAR_DEF;
-
-       smp_mb();
-
-       __asm__ __volatile__(
-       "0:     mov     %[delay], 1             \n"
-       "1:     llock   %[val], [%[slock]]      \n"
-       "       breq    %[val], %[LOCKED], 0b   \n"     /* spin while LOCKED */
-       "       scond   %[LOCKED], [%[slock]]   \n"     /* acquire */
-       "       bz      4f                      \n"     /* done */
-       "                                       \n"
-       SCOND_FAIL_RETRY_ASM
-
-       : [val]         "=&r"   (val)
-         SCOND_FAIL_RETRY_VARS
-       : [slock]       "r"     (&(lock->slock)),
-         [LOCKED]      "r"     (__ARCH_SPIN_LOCK_LOCKED__)
-       : "memory", "cc");
-
-       smp_mb();
-}
-
-/* 1 - lock taken successfully */
-static inline int arch_spin_trylock(arch_spinlock_t *lock)
-{
-       unsigned int val, got_it = 0;
-       SCOND_FAIL_RETRY_VAR_DEF;
-
-       smp_mb();
-
-       __asm__ __volatile__(
-       "0:     mov     %[delay], 1             \n"
-       "1:     llock   %[val], [%[slock]]      \n"
-       "       breq    %[val], %[LOCKED], 4f   \n"     /* already LOCKED, just bail */
-       "       scond   %[LOCKED], [%[slock]]   \n"     /* acquire */
-       "       bz.d    4f                      \n"
-       "       mov.z   %[got_it], 1            \n"     /* got it */
-       "                                       \n"
-       SCOND_FAIL_RETRY_ASM
-
-       : [val]         "=&r"   (val),
-         [got_it]      "+&r"   (got_it)
-         SCOND_FAIL_RETRY_VARS
-       : [slock]       "r"     (&(lock->slock)),
-         [LOCKED]      "r"     (__ARCH_SPIN_LOCK_LOCKED__)
-       : "memory", "cc");
-
-       smp_mb();
-
-       return got_it;
-}
-
-static inline void arch_spin_unlock(arch_spinlock_t *lock)
-{
-       smp_mb();
-
-       lock->slock = __ARCH_SPIN_LOCK_UNLOCKED__;
-
-       smp_mb();
-}
-
-/*
- * Read-write spinlocks, allowing multiple readers but only one writer.
- * Unfair locking as Writers could be starved indefinitely by Reader(s)
- */
-
-static inline void arch_read_lock(arch_rwlock_t *rw)
-{
-       unsigned int val;
-       SCOND_FAIL_RETRY_VAR_DEF;
-
-       smp_mb();
-
-       /*
-        * zero means writer holds the lock exclusively, deny Reader.
-        * Otherwise grant lock to first/subseq reader
-        *
-        *      if (rw->counter > 0) {
-        *              rw->counter--;
-        *              ret = 1;
-        *      }
-        */
-
-       __asm__ __volatile__(
-       "0:     mov     %[delay], 1             \n"
-       "1:     llock   %[val], [%[rwlock]]     \n"
-       "       brls    %[val], %[WR_LOCKED], 0b\n"     /* <= 0: spin while write locked */
-       "       sub     %[val], %[val], 1       \n"     /* reader lock */
-       "       scond   %[val], [%[rwlock]]     \n"
-       "       bz      4f                      \n"     /* done */
-       "                                       \n"
-       SCOND_FAIL_RETRY_ASM
-
-       : [val]         "=&r"   (val)
-         SCOND_FAIL_RETRY_VARS
-       : [rwlock]      "r"     (&(rw->counter)),
-         [WR_LOCKED]   "ir"    (0)
-       : "memory", "cc");
-
-       smp_mb();
-}
-
-/* 1 - lock taken successfully */
-static inline int arch_read_trylock(arch_rwlock_t *rw)
-{
-       unsigned int val, got_it = 0;
-       SCOND_FAIL_RETRY_VAR_DEF;
-
-       smp_mb();
-
-       __asm__ __volatile__(
-       "0:     mov     %[delay], 1             \n"
-       "1:     llock   %[val], [%[rwlock]]     \n"
-       "       brls    %[val], %[WR_LOCKED], 4f\n"     /* <= 0: already write locked, bail */
-       "       sub     %[val], %[val], 1       \n"     /* counter-- */
-       "       scond   %[val], [%[rwlock]]     \n"
-       "       bz.d    4f                      \n"
-       "       mov.z   %[got_it], 1            \n"     /* got it */
-       "                                       \n"
-       SCOND_FAIL_RETRY_ASM
-
-       : [val]         "=&r"   (val),
-         [got_it]      "+&r"   (got_it)
-         SCOND_FAIL_RETRY_VARS
-       : [rwlock]      "r"     (&(rw->counter)),
-         [WR_LOCKED]   "ir"    (0)
-       : "memory", "cc");
-
-       smp_mb();
-
-       return got_it;
-}
-
-static inline void arch_write_lock(arch_rwlock_t *rw)
-{
-       unsigned int val;
-       SCOND_FAIL_RETRY_VAR_DEF;
-
-       smp_mb();
-
-       /*
-        * If reader(s) hold lock (lock < __ARCH_RW_LOCK_UNLOCKED__),
-        * deny writer. Otherwise if unlocked grant to writer
-        * Hence the claim that Linux rwlocks are unfair to writers.
-        * (can be starved for an indefinite time by readers).
-        *
-        *      if (rw->counter == __ARCH_RW_LOCK_UNLOCKED__) {
-        *              rw->counter = 0;
-        *              ret = 1;
-        *      }
-        */
-
-       __asm__ __volatile__(
-       "0:     mov     %[delay], 1             \n"
-       "1:     llock   %[val], [%[rwlock]]     \n"
-       "       brne    %[val], %[UNLOCKED], 0b \n"     /* while !UNLOCKED spin */
-       "       mov     %[val], %[WR_LOCKED]    \n"
-       "       scond   %[val], [%[rwlock]]     \n"
-       "       bz      4f                      \n"
-       "                                       \n"
-       SCOND_FAIL_RETRY_ASM
-
-       : [val]         "=&r"   (val)
-         SCOND_FAIL_RETRY_VARS
-       : [rwlock]      "r"     (&(rw->counter)),
-         [UNLOCKED]    "ir"    (__ARCH_RW_LOCK_UNLOCKED__),
-         [WR_LOCKED]   "ir"    (0)
-       : "memory", "cc");
-
-       smp_mb();
-}
-
-/* 1 - lock taken successfully */
-static inline int arch_write_trylock(arch_rwlock_t *rw)
-{
-       unsigned int val, got_it = 0;
-       SCOND_FAIL_RETRY_VAR_DEF;
-
-       smp_mb();
-
-       __asm__ __volatile__(
-       "0:     mov     %[delay], 1             \n"
-       "1:     llock   %[val], [%[rwlock]]     \n"
-       "       brne    %[val], %[UNLOCKED], 4f \n"     /* !UNLOCKED, bail */
-       "       mov     %[val], %[WR_LOCKED]    \n"
-       "       scond   %[val], [%[rwlock]]     \n"
-       "       bz.d    4f                      \n"
-       "       mov.z   %[got_it], 1            \n"     /* got it */
-       "                                       \n"
-       SCOND_FAIL_RETRY_ASM
-
-       : [val]         "=&r"   (val),
-         [got_it]      "+&r"   (got_it)
-         SCOND_FAIL_RETRY_VARS
-       : [rwlock]      "r"     (&(rw->counter)),
-         [UNLOCKED]    "ir"    (__ARCH_RW_LOCK_UNLOCKED__),
-         [WR_LOCKED]   "ir"    (0)
-       : "memory", "cc");
-
-       smp_mb();
-
-       return got_it;
-}
-
-static inline void arch_read_unlock(arch_rwlock_t *rw)
-{
-       unsigned int val;
-
-       smp_mb();
-
-       /*
-        * rw->counter++;
-        */
-       __asm__ __volatile__(
-       "1:     llock   %[val], [%[rwlock]]     \n"
-       "       add     %[val], %[val], 1       \n"
-       "       scond   %[val], [%[rwlock]]     \n"
-       "       bnz     1b                      \n"
-       "                                       \n"
-       : [val]         "=&r"   (val)
-       : [rwlock]      "r"     (&(rw->counter))
-       : "memory", "cc");
-
-       smp_mb();
-}
-
-static inline void arch_write_unlock(arch_rwlock_t *rw)
-{
-       unsigned int val;
-
-       smp_mb();
-
-       /*
-        * rw->counter = __ARCH_RW_LOCK_UNLOCKED__;
-        */
-       __asm__ __volatile__(
-       "1:     llock   %[val], [%[rwlock]]     \n"
-       "       scond   %[UNLOCKED], [%[rwlock]]\n"
-       "       bnz     1b                      \n"
-       "                                       \n"
-       : [val]         "=&r"   (val)
-       : [rwlock]      "r"     (&(rw->counter)),
-         [UNLOCKED]    "r"     (__ARCH_RW_LOCK_UNLOCKED__)
-       : "memory", "cc");
-
-       smp_mb();
-}
-
-#undef SCOND_FAIL_RETRY_VAR_DEF
-#undef SCOND_FAIL_RETRY_ASM
-#undef SCOND_FAIL_RETRY_VARS
-
-#endif /* CONFIG_ARC_STAR_9000923308 */
-
 #else  /* !CONFIG_ARC_HAS_LLSC */
 
 static inline void arch_spin_lock(arch_spinlock_t *lock)
index 3af6745..2d79e52 100644 (file)
@@ -103,7 +103,7 @@ static inline __attribute_const__ struct thread_info *current_thread_info(void)
 
 /*
  * _TIF_ALLWORK_MASK includes SYSCALL_TRACE, but we don't need it.
- * SYSCALL_TRACE is anways seperately/unconditionally tested right after a
+ * SYSCALL_TRACE is anyway seperately/unconditionally tested right after a
  * syscall, so all that reamins to be tested is _TIF_WORK_MASK
  */
 
index d1da603..a78d567 100644 (file)
@@ -32,7 +32,7 @@
 #define __kernel_ok            (segment_eq(get_fs(), KERNEL_DS))
 
 /*
- * Algorthmically, for __user_ok() we want do:
+ * Algorithmically, for __user_ok() we want do:
  *     (start < TASK_SIZE) && (start+len < TASK_SIZE)
  * where TASK_SIZE could either be retrieved from thread_info->addr_limit or
  * emitted directly in code.
index 095599a..71f3918 100644 (file)
@@ -74,7 +74,7 @@
        __tmp ^ __in;                                           \
 })
 
-#elif (ARC_BSWAP_TYPE == 2)    /* Custom single cycle bwap instruction */
+#elif (ARC_BSWAP_TYPE == 2)    /* Custom single cycle bswap instruction */
 
 #define __arch_swab32(x)                                               \
 ({                                                                     \
index 0cb0aba..98812c1 100644 (file)
@@ -91,27 +91,13 @@ VECTOR   mem_service             ; 0x8, Mem exception   (0x1)
 VECTOR   instr_service           ; 0x10, Instrn Error   (0x2)
 
 ; ******************** Device ISRs **********************
-#ifdef CONFIG_ARC_IRQ3_LV2
-VECTOR   handle_interrupt_level2
-#else
-VECTOR   handle_interrupt_level1
-#endif
-
-VECTOR   handle_interrupt_level1
-
-#ifdef CONFIG_ARC_IRQ5_LV2
-VECTOR   handle_interrupt_level2
-#else
-VECTOR   handle_interrupt_level1
-#endif
-
-#ifdef CONFIG_ARC_IRQ6_LV2
+#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
 VECTOR   handle_interrupt_level2
 #else
 VECTOR   handle_interrupt_level1
 #endif
 
-.rept   25
+.rept   28
 VECTOR   handle_interrupt_level1 ; Other devices
 .endr
 
index c5cceca..ce9deb9 100644 (file)
@@ -28,10 +28,8 @@ void arc_init_IRQ(void)
 {
        int level_mask = 0;
 
-       /* setup any high priority Interrupts (Level2 in ARCompact jargon) */
-       level_mask |= IS_ENABLED(CONFIG_ARC_IRQ3_LV2) << 3;
-       level_mask |= IS_ENABLED(CONFIG_ARC_IRQ5_LV2) << 5;
-       level_mask |= IS_ENABLED(CONFIG_ARC_IRQ6_LV2) << 6;
+       /* Is timer high priority Interrupt (Level2 in ARCompact jargon) */
+       level_mask |= IS_ENABLED(CONFIG_ARC_COMPACT_IRQ_LEVELS) << TIMER0_IRQ;
 
        /*
         * Write to register, even if no LV2 IRQs configured to reset it
index 6fd4802..08f03d9 100644 (file)
@@ -108,7 +108,7 @@ static void arc_perf_event_update(struct perf_event *event,
        int64_t delta = new_raw_count - prev_raw_count;
 
        /*
-        * We don't afaraid of hwc->prev_count changing beneath our feet
+        * We aren't afraid of hwc->prev_count changing beneath our feet
         * because there's no way for us to re-enter this function anytime.
         */
        local64_set(&hwc->prev_count, new_raw_count);
index f63b8bf..2ee7a4d 100644 (file)
@@ -392,7 +392,7 @@ void __init setup_arch(char **cmdline_p)
                /*
                 * If we are here, it is established that @uboot_arg didn't
                 * point to DT blob. Instead if u-boot says it is cmdline,
-                * Appent to embedded DT cmdline.
+                * append to embedded DT cmdline.
                 * setup_machine_fdt() would have populated @boot_command_line
                 */
                if (uboot_tag == 1) {
index 004b7f0..6cb3736 100644 (file)
@@ -34,7 +34,7 @@
  *  -ViXS were still seeing crashes when using insmod to load drivers.
  *   It turned out that the code to change Execute permssions for TLB entries
  *   of user was not guarded for interrupts (mod_tlb_permission)
- *   This was cauing TLB entries to be overwritten on unrelated indexes
+ *   This was causing TLB entries to be overwritten on unrelated indexes
  *
  * Vineetg: July 15th 2008: Bug #94183
  *  -Exception happens in Delay slot of a JMP, and before user space resumes,
index a6f91e8..934150e 100644 (file)
@@ -276,7 +276,7 @@ static int tlb_stats_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-/* called on user read(): display the couters */
+/* called on user read(): display the counters */
 static ssize_t tlb_stats_output(struct file *file,     /* file descriptor */
                                char __user *user_buf,  /* user buffer */
                                size_t len,             /* length of buffer */
index 9e5eddb..5a294b2 100644 (file)
@@ -215,7 +215,7 @@ slc_chk:
  * ------------------
  * This ver of MMU supports variable page sizes (1k-16k): although Linux will
  * only support 8k (default), 16k and 4k.
- * However from hardware perspective, smaller page sizes aggrevate aliasing
+ * However from hardware perspective, smaller page sizes aggravate aliasing
  * meaning more vaddr bits needed to disambiguate the cache-line-op ;
  * the existing scheme of piggybacking won't work for certain configurations.
  * Two new registers IC_PTAG and DC_PTAG inttoduced.
@@ -302,7 +302,7 @@ void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr,
 
        /*
         * This is technically for MMU v4, using the MMU v3 programming model
-        * Special work for HS38 aliasing I-cache configuratino with PAE40
+        * Special work for HS38 aliasing I-cache configuration with PAE40
         *   - upper 8 bits of paddr need to be written into PTAG_HI
         *   - (and needs to be written before the lower 32 bits)
         * Note that PTAG_HI is hoisted outside the line loop
@@ -936,7 +936,7 @@ void arc_cache_init(void)
                              ic->ver, CONFIG_ARC_MMU_VER);
 
                /*
-                * In MMU v4 (HS38x) the alising icache config uses IVIL/PTAG
+                * In MMU v4 (HS38x) the aliasing icache config uses IVIL/PTAG
                 * pair to provide vaddr/paddr respectively, just as in MMU v3
                 */
                if (is_isa_arcv2() && ic->alias)
index 8c8e36f..73d7e4c 100644 (file)
@@ -10,7 +10,7 @@
  * DMA Coherent API Notes
  *
  * I/O is inherently non-coherent on ARC. So a coherent DMA buffer is
- * implemented by accessintg it using a kernel virtual address, with
+ * implemented by accessing it using a kernel virtual address, with
  * Cache bit off in the TLB entry.
  *
  * The default DMA address == Phy address which is 0x8000_0000 based.
index 31e8da6..262ca31 100644 (file)
@@ -1051,7 +1051,7 @@ static int __init acpi_bus_init(void)
         * Maybe EC region is required at bus_scan/acpi_get_devices. So it
         * is necessary to enable it as early as possible.
         */
-       acpi_boot_ec_enable();
+       acpi_ec_dsdt_probe();
 
        printk(KERN_INFO PREFIX "Interpreter enabled\n");
 
index 0e70181..73c76d6 100644 (file)
@@ -1446,10 +1446,30 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context)
        return AE_OK;
 }
 
-int __init acpi_boot_ec_enable(void)
+static const struct acpi_device_id ec_device_ids[] = {
+       {"PNP0C09", 0},
+       {"", 0},
+};
+
+int __init acpi_ec_dsdt_probe(void)
 {
-       if (!boot_ec)
+       acpi_status status;
+
+       if (boot_ec)
                return 0;
+
+       /*
+        * Finding EC from DSDT if there is no ECDT EC available. When this
+        * function is invoked, ACPI tables have been fully loaded, we can
+        * walk namespace now.
+        */
+       boot_ec = make_acpi_ec();
+       if (!boot_ec)
+               return -ENOMEM;
+       status = acpi_get_devices(ec_device_ids[0].id,
+                                 ec_parse_device, boot_ec, NULL);
+       if (ACPI_FAILURE(status) || !boot_ec->handle)
+               return -ENODEV;
        if (!ec_install_handlers(boot_ec)) {
                first_ec = boot_ec;
                return 0;
@@ -1457,11 +1477,6 @@ int __init acpi_boot_ec_enable(void)
        return -EFAULT;
 }
 
-static const struct acpi_device_id ec_device_ids[] = {
-       {"PNP0C09", 0},
-       {"", 0},
-};
-
 #if 0
 /*
  * Some EC firmware variations refuses to respond QR_EC when SCI_EVT is not
index 9bb0773..27cc7fe 100644 (file)
@@ -181,7 +181,7 @@ typedef int (*acpi_ec_query_func) (void *data);
 
 int acpi_ec_init(void);
 int acpi_ec_ecdt_probe(void);
-int acpi_boot_ec_enable(void);
+int acpi_ec_dsdt_probe(void);
 void acpi_ec_block_transactions(void);
 void acpi_ec_unblock_transactions(void);
 void acpi_ec_unblock_transactions_early(void);
index 0d159b5..ee367e9 100644 (file)
@@ -1460,6 +1460,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 
        intel_pstate_clear_update_util_hook(policy->cpu);
 
+       pr_debug("set_policy cpuinfo.max %u policy->max %u\n",
+                policy->cpuinfo.max_freq, policy->max);
+
        cpu = all_cpu_data[0];
        if (cpu->pstate.max_pstate_physical > cpu->pstate.max_pstate &&
            policy->max < policy->cpuinfo.max_freq &&
@@ -1495,13 +1498,13 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
                                   limits->max_sysfs_pct);
        limits->max_perf_pct = max(limits->min_policy_pct,
                                   limits->max_perf_pct);
-       limits->max_perf = round_up(limits->max_perf, FRAC_BITS);
 
        /* Make sure min_perf_pct <= max_perf_pct */
        limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
 
        limits->min_perf = div_fp(limits->min_perf_pct, 100);
        limits->max_perf = div_fp(limits->max_perf_pct, 100);
+       limits->max_perf = round_up(limits->max_perf, FRAC_BITS);
 
  out:
        intel_pstate_set_update_util_hook(policy->cpu);
@@ -1558,8 +1561,11 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
 
        /* cpuinfo and default policy values */
        policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling;
-       policy->cpuinfo.max_freq =
-               cpu->pstate.turbo_pstate * cpu->pstate.scaling;
+       update_turbo_state();
+       policy->cpuinfo.max_freq = limits->turbo_disabled ?
+                       cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
+       policy->cpuinfo.max_freq *= cpu->pstate.scaling;
+
        intel_pstate_init_acpi_perf_limits(policy);
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
        cpumask_set_cpu(policy->cpu, policy->cpus);
index 992f00b..01c36b8 100644 (file)
@@ -799,6 +799,7 @@ struct amdgpu_ring {
        unsigned                cond_exe_offs;
        u64                             cond_exe_gpu_addr;
        volatile u32    *cond_exe_cpu_addr;
+       int                     vmid;
 };
 
 /*
@@ -936,7 +937,8 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring,
                    unsigned vm_id, uint64_t pd_addr,
                    uint32_t gds_base, uint32_t gds_size,
                    uint32_t gws_base, uint32_t gws_size,
-                   uint32_t oa_base, uint32_t oa_size);
+                   uint32_t oa_base, uint32_t oa_size,
+                   bool vmid_switch);
 void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id);
 uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr);
 int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
index 199f76b..8943099 100644 (file)
@@ -696,6 +696,17 @@ static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type)
        return result;
 }
 
+static int amdgpu_cgs_rel_firmware(struct cgs_device *cgs_device, enum cgs_ucode_id type)
+{
+       CGS_FUNC_ADEV;
+       if ((CGS_UCODE_ID_SMU == type) || (CGS_UCODE_ID_SMU_SK == type)) {
+               release_firmware(adev->pm.fw);
+               return 0;
+       }
+       /* cannot release other firmware because they are not created by cgs */
+       return -EINVAL;
+}
+
 static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
                                        enum cgs_ucode_id type,
                                        struct cgs_firmware_info *info)
@@ -1125,6 +1136,7 @@ static const struct cgs_ops amdgpu_cgs_ops = {
        amdgpu_cgs_pm_query_clock_limits,
        amdgpu_cgs_set_camera_voltages,
        amdgpu_cgs_get_firmware_info,
+       amdgpu_cgs_rel_firmware,
        amdgpu_cgs_set_powergating_state,
        amdgpu_cgs_set_clockgating_state,
        amdgpu_cgs_get_active_displays_info,
index bb8b149..964f314 100644 (file)
@@ -827,8 +827,10 @@ static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg)
  */
 static void amdgpu_atombios_fini(struct amdgpu_device *adev)
 {
-       if (adev->mode_info.atom_context)
+       if (adev->mode_info.atom_context) {
                kfree(adev->mode_info.atom_context->scratch);
+               kfree(adev->mode_info.atom_context->iio);
+       }
        kfree(adev->mode_info.atom_context);
        adev->mode_info.atom_context = NULL;
        kfree(adev->mode_info.atom_card_info);
@@ -1325,6 +1327,11 @@ static int amdgpu_fini(struct amdgpu_device *adev)
                adev->ip_block_status[i].valid = false;
        }
 
+       for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
+               if (adev->ip_blocks[i].funcs->late_fini)
+                       adev->ip_blocks[i].funcs->late_fini((void *)adev);
+       }
+
        return 0;
 }
 
@@ -1513,8 +1520,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
                amdgpu_atombios_has_gpu_virtualization_table(adev);
 
        /* Post card if necessary */
-       if (!amdgpu_card_posted(adev) ||
-           adev->virtualization.supports_sr_iov) {
+       if (!amdgpu_card_posted(adev)) {
                if (!adev->bios) {
                        dev_err(adev->dev, "Card not posted and no BIOS - ignoring\n");
                        return -EINVAL;
index 34e3542..7a0b1e5 100644 (file)
@@ -122,6 +122,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
        bool skip_preamble, need_ctx_switch;
        unsigned patch_offset = ~0;
        struct amdgpu_vm *vm;
+       int vmid = 0, old_vmid = ring->vmid;
        struct fence *hwf;
        uint64_t ctx;
 
@@ -135,9 +136,11 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
        if (job) {
                vm = job->vm;
                ctx = job->ctx;
+               vmid = job->vm_id;
        } else {
                vm = NULL;
                ctx = 0;
+               vmid = 0;
        }
 
        if (!ring->ready) {
@@ -163,7 +166,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
                r = amdgpu_vm_flush(ring, job->vm_id, job->vm_pd_addr,
                                    job->gds_base, job->gds_size,
                                    job->gws_base, job->gws_size,
-                                   job->oa_base, job->oa_size);
+                                   job->oa_base, job->oa_size,
+                                   (ring->current_ctx == ctx) && (old_vmid != vmid));
                if (r) {
                        amdgpu_ring_undo(ring);
                        return r;
@@ -180,7 +184,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
        need_ctx_switch = ring->current_ctx != ctx;
        for (i = 0; i < num_ibs; ++i) {
                ib = &ibs[i];
-
                /* drop preamble IBs if we don't have a context switch */
                if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && skip_preamble)
                        continue;
@@ -188,6 +191,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
                amdgpu_ring_emit_ib(ring, ib, job ? job->vm_id : 0,
                                    need_ctx_switch);
                need_ctx_switch = false;
+               ring->vmid = vmid;
        }
 
        if (ring->funcs->emit_hdp_invalidate)
@@ -198,6 +202,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
                dev_err(adev->dev, "failed to emit fence (%d)\n", r);
                if (job && job->vm_id)
                        amdgpu_vm_reset_id(adev, job->vm_id);
+               ring->vmid = old_vmid;
                amdgpu_ring_undo(ring);
                return r;
        }
index 6bd961f..8225655 100644 (file)
@@ -183,13 +183,6 @@ static int amdgpu_pp_sw_fini(void *handle)
        if (ret)
                return ret;
 
-#ifdef CONFIG_DRM_AMD_POWERPLAY
-       if (adev->pp_enabled) {
-               amdgpu_pm_sysfs_fini(adev);
-               amd_powerplay_fini(adev->powerplay.pp_handle);
-       }
-#endif
-
        return ret;
 }
 
@@ -223,6 +216,22 @@ static int amdgpu_pp_hw_fini(void *handle)
        return ret;
 }
 
+static void amdgpu_pp_late_fini(void *handle)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       if (adev->pp_enabled) {
+               amdgpu_pm_sysfs_fini(adev);
+               amd_powerplay_fini(adev->powerplay.pp_handle);
+       }
+
+       if (adev->powerplay.ip_funcs->late_fini)
+               adev->powerplay.ip_funcs->late_fini(
+                         adev->powerplay.pp_handle);
+#endif
+}
+
 static int amdgpu_pp_suspend(void *handle)
 {
        int ret = 0;
@@ -311,6 +320,7 @@ const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
        .sw_fini = amdgpu_pp_sw_fini,
        .hw_init = amdgpu_pp_hw_init,
        .hw_fini = amdgpu_pp_hw_fini,
+       .late_fini = amdgpu_pp_late_fini,
        .suspend = amdgpu_pp_suspend,
        .resume = amdgpu_pp_resume,
        .is_idle = amdgpu_pp_is_idle,
index 3b02272..870f949 100644 (file)
@@ -343,6 +343,7 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
        ring->ring = NULL;
        ring->ring_obj = NULL;
 
+       amdgpu_wb_free(ring->adev, ring->cond_exe_offs);
        amdgpu_wb_free(ring->adev, ring->fence_offs);
        amdgpu_wb_free(ring->adev, ring->rptr_offs);
        amdgpu_wb_free(ring->adev, ring->wptr_offs);
index 8bf84ef..48618ee 100644 (file)
@@ -115,6 +115,7 @@ int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev,
                return r;
        }
        r = amdgpu_bo_kmap(sa_manager->bo, &sa_manager->cpu_ptr);
+       memset(sa_manager->cpu_ptr, 0, sa_manager->size);
        amdgpu_bo_unreserve(sa_manager->bo);
        return r;
 }
index 01abfc2..e19520c 100644 (file)
@@ -253,19 +253,20 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
 {
        int r;
 
-       if (adev->uvd.vcpu_bo == NULL)
-               return 0;
+       kfree(adev->uvd.saved_bo);
 
        amd_sched_entity_fini(&adev->uvd.ring.sched, &adev->uvd.entity);
 
-       r = amdgpu_bo_reserve(adev->uvd.vcpu_bo, false);
-       if (!r) {
-               amdgpu_bo_kunmap(adev->uvd.vcpu_bo);
-               amdgpu_bo_unpin(adev->uvd.vcpu_bo);
-               amdgpu_bo_unreserve(adev->uvd.vcpu_bo);
-       }
+       if (adev->uvd.vcpu_bo) {
+               r = amdgpu_bo_reserve(adev->uvd.vcpu_bo, false);
+               if (!r) {
+                       amdgpu_bo_kunmap(adev->uvd.vcpu_bo);
+                       amdgpu_bo_unpin(adev->uvd.vcpu_bo);
+                       amdgpu_bo_unreserve(adev->uvd.vcpu_bo);
+               }
 
-       amdgpu_bo_unref(&adev->uvd.vcpu_bo);
+               amdgpu_bo_unref(&adev->uvd.vcpu_bo);
+       }
 
        amdgpu_ring_fini(&adev->uvd.ring);
 
index 9f36ed3..62a4c12 100644 (file)
@@ -298,7 +298,8 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring,
                    unsigned vm_id, uint64_t pd_addr,
                    uint32_t gds_base, uint32_t gds_size,
                    uint32_t gws_base, uint32_t gws_size,
-                   uint32_t oa_base, uint32_t oa_size)
+                   uint32_t oa_base, uint32_t oa_size,
+                   bool vmid_switch)
 {
        struct amdgpu_device *adev = ring->adev;
        struct amdgpu_vm_id *id = &adev->vm_manager.ids[vm_id];
@@ -312,8 +313,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring,
        int r;
 
        if (ring->funcs->emit_pipeline_sync && (
-           pd_addr != AMDGPU_VM_NO_FLUSH || gds_switch_needed ||
-                   ring->type == AMDGPU_RING_TYPE_COMPUTE))
+           pd_addr != AMDGPU_VM_NO_FLUSH || gds_switch_needed || vmid_switch))
                amdgpu_ring_emit_pipeline_sync(ring);
 
        if (ring->funcs->emit_vm_flush &&
index ea407db..5ec1f1e 100644 (file)
@@ -6221,6 +6221,9 @@ static int ci_dpm_sw_fini(void *handle)
        ci_dpm_fini(adev);
        mutex_unlock(&adev->pm.mutex);
 
+       release_firmware(adev->pm.fw);
+       adev->pm.fw = NULL;
+
        return 0;
 }
 
index 518dca4..9dc4e24 100644 (file)
@@ -66,6 +66,16 @@ MODULE_FIRMWARE("radeon/mullins_sdma1.bin");
 
 u32 amdgpu_cik_gpu_check_soft_reset(struct amdgpu_device *adev);
 
+
+static void cik_sdma_free_microcode(struct amdgpu_device *adev)
+{
+       int i;
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+                       release_firmware(adev->sdma.instance[i].fw);
+                       adev->sdma.instance[i].fw = NULL;
+       }
+}
+
 /*
  * sDMA - System DMA
  * Starting with CIK, the GPU has new asynchronous
@@ -419,6 +429,8 @@ static int cik_sdma_gfx_resume(struct amdgpu_device *adev)
                /* Initialize the ring buffer's read and write pointers */
                WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
                WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
+               WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
+               WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);
 
                /* set the wb address whether it's enabled or not */
                WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
@@ -446,7 +458,12 @@ static int cik_sdma_gfx_resume(struct amdgpu_device *adev)
                WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
 
                ring->ready = true;
+       }
+
+       cik_sdma_enable(adev, true);
 
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+               ring = &adev->sdma.instance[i].ring;
                r = amdgpu_ring_test_ring(ring);
                if (r) {
                        ring->ready = false;
@@ -529,8 +546,8 @@ static int cik_sdma_start(struct amdgpu_device *adev)
        if (r)
                return r;
 
-       /* unhalt the MEs */
-       cik_sdma_enable(adev, true);
+       /* halt the engine before programing */
+       cik_sdma_enable(adev, false);
 
        /* start the gfx rings and rlc compute queues */
        r = cik_sdma_gfx_resume(adev);
@@ -998,6 +1015,7 @@ static int cik_sdma_sw_fini(void *handle)
        for (i = 0; i < adev->sdma.num_instances; i++)
                amdgpu_ring_fini(&adev->sdma.instance[i].ring);
 
+       cik_sdma_free_microcode(adev);
        return 0;
 }
 
index 245cabf..ed03b75 100644 (file)
@@ -72,6 +72,11 @@ static int fiji_dpm_sw_init(void *handle)
 
 static int fiji_dpm_sw_fini(void *handle)
 {
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       release_firmware(adev->pm.fw);
+       adev->pm.fw = NULL;
+
        return 0;
 }
 
index 7f18a53..8c6ad1e 100644 (file)
@@ -991,6 +991,22 @@ out:
        return err;
 }
 
+static void gfx_v7_0_free_microcode(struct amdgpu_device *adev)
+{
+       release_firmware(adev->gfx.pfp_fw);
+       adev->gfx.pfp_fw = NULL;
+       release_firmware(adev->gfx.me_fw);
+       adev->gfx.me_fw = NULL;
+       release_firmware(adev->gfx.ce_fw);
+       adev->gfx.ce_fw = NULL;
+       release_firmware(adev->gfx.mec_fw);
+       adev->gfx.mec_fw = NULL;
+       release_firmware(adev->gfx.mec2_fw);
+       adev->gfx.mec2_fw = NULL;
+       release_firmware(adev->gfx.rlc_fw);
+       adev->gfx.rlc_fw = NULL;
+}
+
 /**
  * gfx_v7_0_tiling_mode_table_init - init the hw tiling table
  *
@@ -4489,6 +4505,7 @@ static int gfx_v7_0_sw_fini(void *handle)
        gfx_v7_0_cp_compute_fini(adev);
        gfx_v7_0_rlc_fini(adev);
        gfx_v7_0_mec_fini(adev);
+       gfx_v7_0_free_microcode(adev);
 
        return 0;
 }
index f19bab6..9f6f866 100644 (file)
@@ -836,6 +836,26 @@ err1:
        return r;
 }
 
+
+static void gfx_v8_0_free_microcode(struct amdgpu_device *adev) {
+       release_firmware(adev->gfx.pfp_fw);
+       adev->gfx.pfp_fw = NULL;
+       release_firmware(adev->gfx.me_fw);
+       adev->gfx.me_fw = NULL;
+       release_firmware(adev->gfx.ce_fw);
+       adev->gfx.ce_fw = NULL;
+       release_firmware(adev->gfx.rlc_fw);
+       adev->gfx.rlc_fw = NULL;
+       release_firmware(adev->gfx.mec_fw);
+       adev->gfx.mec_fw = NULL;
+       if ((adev->asic_type != CHIP_STONEY) &&
+           (adev->asic_type != CHIP_TOPAZ))
+               release_firmware(adev->gfx.mec2_fw);
+       adev->gfx.mec2_fw = NULL;
+
+       kfree(adev->gfx.rlc.register_list_format);
+}
+
 static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
 {
        const char *chip_name;
@@ -1983,7 +2003,7 @@ static int gfx_v8_0_sw_fini(void *handle)
 
        gfx_v8_0_rlc_fini(adev);
 
-       kfree(adev->gfx.rlc.register_list_format);
+       gfx_v8_0_free_microcode(adev);
 
        return 0;
 }
@@ -3974,11 +3994,15 @@ static int gfx_v8_0_cp_gfx_start(struct amdgpu_device *adev)
                amdgpu_ring_write(ring, 0x3a00161a);
                amdgpu_ring_write(ring, 0x0000002e);
                break;
-       case CHIP_TOPAZ:
        case CHIP_CARRIZO:
                amdgpu_ring_write(ring, 0x00000002);
                amdgpu_ring_write(ring, 0x00000000);
                break;
+       case CHIP_TOPAZ:
+               amdgpu_ring_write(ring, adev->gfx.config.num_rbs == 1 ?
+                               0x00000000 : 0x00000002);
+               amdgpu_ring_write(ring, 0x00000000);
+               break;
        case CHIP_STONEY:
                amdgpu_ring_write(ring, 0x00000000);
                amdgpu_ring_write(ring, 0x00000000);
index 460bc8a..825ccd6 100644 (file)
@@ -72,6 +72,11 @@ static int iceland_dpm_sw_init(void *handle)
 
 static int iceland_dpm_sw_fini(void *handle)
 {
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       release_firmware(adev->pm.fw);
+       adev->pm.fw = NULL;
+
        return 0;
 }
 
index f4c3130..b556bd0 100644 (file)
@@ -105,6 +105,15 @@ static void sdma_v2_4_init_golden_registers(struct amdgpu_device *adev)
        }
 }
 
+static void sdma_v2_4_free_microcode(struct amdgpu_device *adev)
+{
+       int i;
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+               release_firmware(adev->sdma.instance[i].fw);
+               adev->sdma.instance[i].fw = NULL;
+       }
+}
+
 /**
  * sdma_v2_4_init_microcode - load ucode images from disk
  *
@@ -461,6 +470,8 @@ static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev)
                /* Initialize the ring buffer's read and write pointers */
                WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
                WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
+               WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
+               WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);
 
                /* set the wb address whether it's enabled or not */
                WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
@@ -489,7 +500,11 @@ static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev)
                WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
 
                ring->ready = true;
+       }
 
+       sdma_v2_4_enable(adev, true);
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+               ring = &adev->sdma.instance[i].ring;
                r = amdgpu_ring_test_ring(ring);
                if (r) {
                        ring->ready = false;
@@ -580,8 +595,8 @@ static int sdma_v2_4_start(struct amdgpu_device *adev)
                        return -EINVAL;
        }
 
-       /* unhalt the MEs */
-       sdma_v2_4_enable(adev, true);
+       /* halt the engine before programing */
+       sdma_v2_4_enable(adev, false);
 
        /* start the gfx rings and rlc compute queues */
        r = sdma_v2_4_gfx_resume(adev);
@@ -1012,6 +1027,7 @@ static int sdma_v2_4_sw_fini(void *handle)
        for (i = 0; i < adev->sdma.num_instances; i++)
                amdgpu_ring_fini(&adev->sdma.instance[i].ring);
 
+       sdma_v2_4_free_microcode(adev);
        return 0;
 }
 
index 31d99b0..532ea88 100644 (file)
@@ -236,6 +236,15 @@ static void sdma_v3_0_init_golden_registers(struct amdgpu_device *adev)
        }
 }
 
+static void sdma_v3_0_free_microcode(struct amdgpu_device *adev)
+{
+       int i;
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+               release_firmware(adev->sdma.instance[i].fw);
+               adev->sdma.instance[i].fw = NULL;
+       }
+}
+
 /**
  * sdma_v3_0_init_microcode - load ucode images from disk
  *
@@ -672,6 +681,8 @@ static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev)
                /* Initialize the ring buffer's read and write pointers */
                WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
                WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
+               WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
+               WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);
 
                /* set the wb address whether it's enabled or not */
                WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
@@ -711,7 +722,15 @@ static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev)
                WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
 
                ring->ready = true;
+       }
+
+       /* unhalt the MEs */
+       sdma_v3_0_enable(adev, true);
+       /* enable sdma ring preemption */
+       sdma_v3_0_ctx_switch_enable(adev, true);
 
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+               ring = &adev->sdma.instance[i].ring;
                r = amdgpu_ring_test_ring(ring);
                if (r) {
                        ring->ready = false;
@@ -804,10 +823,9 @@ static int sdma_v3_0_start(struct amdgpu_device *adev)
                }
        }
 
-       /* unhalt the MEs */
-       sdma_v3_0_enable(adev, true);
-       /* enable sdma ring preemption */
-       sdma_v3_0_ctx_switch_enable(adev, true);
+       /* disble sdma engine before programing it */
+       sdma_v3_0_ctx_switch_enable(adev, false);
+       sdma_v3_0_enable(adev, false);
 
        /* start the gfx rings and rlc compute queues */
        r = sdma_v3_0_gfx_resume(adev);
@@ -1247,6 +1265,7 @@ static int sdma_v3_0_sw_fini(void *handle)
        for (i = 0; i < adev->sdma.num_instances; i++)
                amdgpu_ring_fini(&adev->sdma.instance[i].ring);
 
+       sdma_v3_0_free_microcode(adev);
        return 0;
 }
 
index b7615ce..f06f6f4 100644 (file)
@@ -71,6 +71,11 @@ static int tonga_dpm_sw_init(void *handle)
 
 static int tonga_dpm_sw_fini(void *handle)
 {
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       release_firmware(adev->pm.fw);
+       adev->pm.fw = NULL;
+
        return 0;
 }
 
index 6080951..afce1ed 100644 (file)
@@ -157,6 +157,7 @@ struct amd_ip_funcs {
        int (*hw_init)(void *handle);
        /* tears down the hw state */
        int (*hw_fini)(void *handle);
+       void (*late_fini)(void *handle);
        /* handles IP specific hw/sw changes for suspend */
        int (*suspend)(void *handle);
        /* handles IP specific hw/sw changes for resume */
index a461e15..7464daf 100644 (file)
@@ -581,6 +581,9 @@ typedef int (*cgs_get_firmware_info)(struct cgs_device *cgs_device,
                                     enum cgs_ucode_id type,
                                     struct cgs_firmware_info *info);
 
+typedef int (*cgs_rel_firmware)(struct cgs_device *cgs_device,
+                                        enum cgs_ucode_id type);
+
 typedef int(*cgs_set_powergating_state)(struct cgs_device *cgs_device,
                                  enum amd_ip_block_type block_type,
                                  enum amd_powergating_state state);
@@ -645,6 +648,7 @@ struct cgs_ops {
        cgs_set_camera_voltages_t set_camera_voltages;
        /* Firmware Info */
        cgs_get_firmware_info get_firmware_info;
+       cgs_rel_firmware rel_firmware;
        /* cg pg interface*/
        cgs_set_powergating_state set_powergating_state;
        cgs_set_clockgating_state set_clockgating_state;
@@ -738,6 +742,8 @@ struct cgs_device
        CGS_CALL(set_camera_voltages,dev,mask,voltages)
 #define cgs_get_firmware_info(dev, type, info) \
        CGS_CALL(get_firmware_info, dev, type, info)
+#define cgs_rel_firmware(dev, type)    \
+       CGS_CALL(rel_firmware, dev, type)
 #define cgs_set_powergating_state(dev, block_type, state)      \
        CGS_CALL(set_powergating_state, dev, block_type, state)
 #define cgs_set_clockgating_state(dev, block_type, state)      \
index 8e345bf..e629f8a 100644 (file)
@@ -73,11 +73,14 @@ static int pp_sw_init(void *handle)
 
        ret = hwmgr->hwmgr_func->backend_init(hwmgr);
        if (ret)
-               goto err;
+               goto err1;
 
        pr_info("amdgpu: powerplay initialized\n");
 
        return 0;
+err1:
+       if (hwmgr->pptable_func->pptable_fini)
+               hwmgr->pptable_func->pptable_fini(hwmgr);
 err:
        pr_err("amdgpu: powerplay initialization failed\n");
        return ret;
@@ -100,6 +103,9 @@ static int pp_sw_fini(void *handle)
        if (hwmgr->hwmgr_func->backend_fini != NULL)
                ret = hwmgr->hwmgr_func->backend_fini(hwmgr);
 
+       if (hwmgr->pptable_func->pptable_fini)
+               hwmgr->pptable_func->pptable_fini(hwmgr);
+
        return ret;
 }
 
index 46410e3..fb88e4e 100644 (file)
@@ -58,9 +58,6 @@ static void pem_fini(struct pp_eventmgr *eventmgr)
        pem_unregister_interrupts(eventmgr);
 
        pem_handle_event(eventmgr, AMD_PP_EVENT_UNINITIALIZE, &event_data);
-
-       if (eventmgr != NULL)
-               kfree(eventmgr);
 }
 
 int eventmgr_init(struct pp_instance *handle)
index 24a16e4..586f732 100644 (file)
@@ -1830,7 +1830,7 @@ static uint16_t fiji_find_closest_vddci(struct pp_hwmgr *hwmgr, uint16_t vddci)
 
        PP_ASSERT_WITH_CODE(false,
                        "VDDCI is larger than max VDDCI in VDDCI Voltage Table!",
-                       return vddci_table->entries[i].value);
+                       return vddci_table->entries[i-1].value);
 }
 
 static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
index 1c48917..20f20e0 100644 (file)
@@ -93,6 +93,13 @@ int hwmgr_fini(struct pp_hwmgr *hwmgr)
        if (hwmgr == NULL || hwmgr->ps == NULL)
                return -EINVAL;
 
+       /* do hwmgr finish*/
+       kfree(hwmgr->backend);
+
+       kfree(hwmgr->start_thermal_controller.function_list);
+
+       kfree(hwmgr->set_temperature_range.function_list);
+
        kfree(hwmgr->ps);
        kfree(hwmgr);
        return 0;
@@ -462,7 +469,7 @@ uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, u
 
        PP_ASSERT_WITH_CODE(false,
                        "VDDCI is larger than max VDDCI in VDDCI Voltage Table!",
-                       return vddci_table->entries[i].value);
+                       return vddci_table->entries[i-1].value);
 }
 
 int phm_find_boot_level(void *table,
index 0b99ab3..ae96f14 100644 (file)
@@ -286,7 +286,7 @@ int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr)
 
                if (polaris10_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset,
                                (uint8_t *)&data->power_tune_table,
-                               sizeof(struct SMU74_Discrete_PmFuses), data->sram_end))
+                               (sizeof(struct SMU74_Discrete_PmFuses) - 92), data->sram_end))
                        PP_ASSERT_WITH_CODE(false,
                                        "Attempt to download PmFuseTable Failed!",
                                        return -EINVAL);
index 16fed48..d27e8c4 100644 (file)
@@ -2847,27 +2847,6 @@ static int tonga_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
                }
        }
 
-       /* Initialize Vddc DPM table based on allow Vddc values.  And populate corresponding std values. */
-       for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
-               data->dpm_table.vddc_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].vddc;
-               /* tonga_hwmgr->dpm_table.VddcTable.dpm_levels[i].param1 = stdVoltageTable->entries[i].Leakage; */
-               /* param1 is for corresponding std voltage */
-               data->dpm_table.vddc_table.dpm_levels[i].enabled = 1;
-       }
-       data->dpm_table.vddc_table.count = allowed_vdd_sclk_table->count;
-
-       if (NULL != allowed_vdd_mclk_table) {
-               /* Initialize Vddci DPM table based on allow Mclk values */
-               for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
-                       data->dpm_table.vdd_ci_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].vddci;
-                       data->dpm_table.vdd_ci_table.dpm_levels[i].enabled = 1;
-                       data->dpm_table.mvdd_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].mvdd;
-                       data->dpm_table.mvdd_table.dpm_levels[i].enabled = 1;
-               }
-               data->dpm_table.vdd_ci_table.count = allowed_vdd_mclk_table->count;
-               data->dpm_table.mvdd_table.count = allowed_vdd_mclk_table->count;
-       }
-
        /* setup PCIE gen speed levels*/
        tonga_setup_default_pcie_tables(hwmgr);
 
index 10e3630..296ec7e 100644 (file)
@@ -1040,48 +1040,44 @@ int tonga_pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
        struct phm_ppt_v1_information *pp_table_information =
                (struct phm_ppt_v1_information *)(hwmgr->pptable);
 
-       if (NULL != hwmgr->soft_pp_table) {
-               kfree(hwmgr->soft_pp_table);
+       if (NULL != hwmgr->soft_pp_table)
                hwmgr->soft_pp_table = NULL;
-       }
 
-       if (NULL != pp_table_information->vdd_dep_on_sclk)
-               pp_table_information->vdd_dep_on_sclk = NULL;
+       kfree(pp_table_information->vdd_dep_on_sclk);
+       pp_table_information->vdd_dep_on_sclk = NULL;
 
-       if (NULL != pp_table_information->vdd_dep_on_mclk)
-               pp_table_information->vdd_dep_on_mclk = NULL;
+       kfree(pp_table_information->vdd_dep_on_mclk);
+       pp_table_information->vdd_dep_on_mclk = NULL;
 
-       if (NULL != pp_table_information->valid_mclk_values)
-               pp_table_information->valid_mclk_values = NULL;
+       kfree(pp_table_information->valid_mclk_values);
+       pp_table_information->valid_mclk_values = NULL;
 
-       if (NULL != pp_table_information->valid_sclk_values)
-               pp_table_information->valid_sclk_values = NULL;
+       kfree(pp_table_information->valid_sclk_values);
+       pp_table_information->valid_sclk_values = NULL;
 
-       if (NULL != pp_table_information->vddc_lookup_table)
-               pp_table_information->vddc_lookup_table = NULL;
+       kfree(pp_table_information->vddc_lookup_table);
+       pp_table_information->vddc_lookup_table = NULL;
 
-       if (NULL != pp_table_information->vddgfx_lookup_table)
-               pp_table_information->vddgfx_lookup_table = NULL;
+       kfree(pp_table_information->vddgfx_lookup_table);
+       pp_table_information->vddgfx_lookup_table = NULL;
 
-       if (NULL != pp_table_information->mm_dep_table)
-               pp_table_information->mm_dep_table = NULL;
+       kfree(pp_table_information->mm_dep_table);
+       pp_table_information->mm_dep_table = NULL;
 
-       if (NULL != pp_table_information->cac_dtp_table)
-               pp_table_information->cac_dtp_table = NULL;
+       kfree(pp_table_information->cac_dtp_table);
+       pp_table_information->cac_dtp_table = NULL;
 
-       if (NULL != hwmgr->dyn_state.cac_dtp_table)
-               hwmgr->dyn_state.cac_dtp_table = NULL;
+       kfree(hwmgr->dyn_state.cac_dtp_table);
+       hwmgr->dyn_state.cac_dtp_table = NULL;
 
-       if (NULL != pp_table_information->ppm_parameter_table)
-               pp_table_information->ppm_parameter_table = NULL;
+       kfree(pp_table_information->ppm_parameter_table);
+       pp_table_information->ppm_parameter_table = NULL;
 
-       if (NULL != pp_table_information->pcie_table)
-               pp_table_information->pcie_table = NULL;
+       kfree(pp_table_information->pcie_table);
+       pp_table_information->pcie_table = NULL;
 
-       if (NULL != hwmgr->pptable) {
-               kfree(hwmgr->pptable);
-               hwmgr->pptable = NULL;
-       }
+       kfree(hwmgr->pptable);
+       hwmgr->pptable = NULL;
 
        return result;
 }
index 673a75c..8e52a2e 100644 (file)
@@ -1006,10 +1006,16 @@ static int fiji_smu_init(struct pp_smumgr *smumgr)
 
 static int fiji_smu_fini(struct pp_smumgr *smumgr)
 {
+       struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
+
+       smu_free_memory(smumgr->device, (void *)priv->header_buffer.handle);
+
        if (smumgr->backend) {
                kfree(smumgr->backend);
                smumgr->backend = NULL;
        }
+
+       cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU);
        return 0;
 }
 
index de618ea..043b6ac 100644 (file)
@@ -469,6 +469,7 @@ int polaris10_smu_fini(struct pp_smumgr *smumgr)
                kfree(smumgr->backend);
                smumgr->backend = NULL;
        }
+       cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU);
        return 0;
 }
 
index c483baf..0728c1e 100644 (file)
@@ -81,6 +81,7 @@ int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
 
 int smum_fini(struct pp_smumgr *smumgr)
 {
+       kfree(smumgr->device);
        kfree(smumgr);
        return 0;
 }
index 32820b6..b22722e 100644 (file)
@@ -328,10 +328,17 @@ int tonga_write_smc_sram_dword(struct pp_smumgr *smumgr,
 
 static int tonga_smu_fini(struct pp_smumgr *smumgr)
 {
+       struct tonga_smumgr *priv = (struct tonga_smumgr *)(smumgr->backend);
+
+       smu_free_memory(smumgr->device, (void *)priv->smu_buffer.handle);
+       smu_free_memory(smumgr->device, (void *)priv->header_buffer.handle);
+
        if (smumgr->backend != NULL) {
                kfree(smumgr->backend);
                smumgr->backend = NULL;
        }
+
+       cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU);
        return 0;
 }
 
index 0ec1ad9..dc723f7 100644 (file)
@@ -42,9 +42,10 @@ static const struct regmap_config fsl_dcu_regmap_config = {
        .reg_bits = 32,
        .reg_stride = 4,
        .val_bits = 32,
-       .cache_type = REGCACHE_RBTREE,
+       .cache_type = REGCACHE_FLAT,
 
        .volatile_reg = fsl_dcu_drm_is_volatile_reg,
+       .max_register = 0x11fc,
 };
 
 static int fsl_dcu_drm_irq_init(struct drm_device *dev)
index fbe304e..2aec27d 100644 (file)
@@ -408,7 +408,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
        }
 
        adreno_gpu->memptrs = msm_gem_vaddr(adreno_gpu->memptrs_bo);
-       if (!adreno_gpu->memptrs) {
+       if (IS_ERR(adreno_gpu->memptrs)) {
                dev_err(drm->dev, "could not vmap memptrs\n");
                return -ENOMEM;
        }
index d9759bf..c6cf837 100644 (file)
@@ -159,6 +159,10 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
        dev->mode_config.fb_base = paddr;
 
        fbi->screen_base = msm_gem_vaddr_locked(fbdev->bo);
+       if (IS_ERR(fbi->screen_base)) {
+               ret = PTR_ERR(fbi->screen_base);
+               goto fail_unlock;
+       }
        fbi->screen_size = fbdev->bo->size;
        fbi->fix.smem_start = paddr;
        fbi->fix.smem_len = fbdev->bo->size;
index 7daf405..69836f5 100644 (file)
@@ -398,6 +398,8 @@ void *msm_gem_vaddr_locked(struct drm_gem_object *obj)
                        return ERR_CAST(pages);
                msm_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT,
                                VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+               if (msm_obj->vaddr == NULL)
+                       return ERR_PTR(-ENOMEM);
        }
        return msm_obj->vaddr;
 }
index b89ca51..eb4bb8b 100644 (file)
@@ -40,12 +40,14 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
 
        submit->dev = dev;
        submit->gpu = gpu;
+       submit->fence = NULL;
        submit->pid = get_pid(task_pid(current));
 
        /* initially, until copy_from_user() and bo lookup succeeds: */
        submit->nr_bos = 0;
        submit->nr_cmds = 0;
 
+       INIT_LIST_HEAD(&submit->node);
        INIT_LIST_HEAD(&submit->bo_list);
        ww_acquire_init(&submit->ticket, &reservation_ww_class);
 
@@ -75,6 +77,11 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
                void __user *userptr =
                        u64_to_user_ptr(args->bos + (i * sizeof(submit_bo)));
 
+               /* make sure we don't have garbage flags, in case we hit
+                * error path before flags is initialized:
+                */
+               submit->bos[i].flags = 0;
+
                ret = copy_from_user(&submit_bo, userptr, sizeof(submit_bo));
                if (ret) {
                        ret = -EFAULT;
index b48f73a..0857710 100644 (file)
@@ -312,6 +312,9 @@ void msm_rd_dump_submit(struct msm_gem_submit *submit)
                struct msm_gem_object *obj = submit->bos[idx].obj;
                const char *buf = msm_gem_vaddr_locked(&obj->base);
 
+               if (IS_ERR(buf))
+                       continue;
+
                buf += iova - submit->bos[idx].iova;
 
                rd_write_section(rd, RD_GPUADDR,
index 1f14b90..42f5359 100644 (file)
@@ -40,6 +40,10 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int size)
        }
 
        ring->start = msm_gem_vaddr_locked(ring->bo);
+       if (IS_ERR(ring->start)) {
+               ret = PTR_ERR(ring->start);
+               goto fail;
+       }
        ring->end   = ring->start + (size / 4);
        ring->cur   = ring->start;
 
index c612dc1..126a85c 100644 (file)
@@ -16,9 +16,9 @@ enum nvkm_devidx {
        NVKM_SUBDEV_MC,
        NVKM_SUBDEV_BUS,
        NVKM_SUBDEV_TIMER,
+       NVKM_SUBDEV_INSTMEM,
        NVKM_SUBDEV_FB,
        NVKM_SUBDEV_LTC,
-       NVKM_SUBDEV_INSTMEM,
        NVKM_SUBDEV_MMU,
        NVKM_SUBDEV_BAR,
        NVKM_SUBDEV_PMU,
index db10c11..c5a6ebd 100644 (file)
@@ -25,7 +25,8 @@ u16 nvbios_outp_match(struct nvkm_bios *, u16 type, u16 mask,
                      u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_outp *);
 
 struct nvbios_ocfg {
-       u16 match;
+       u8  proto;
+       u8  flags;
        u16 clkcmp[2];
 };
 
@@ -33,7 +34,7 @@ u16 nvbios_ocfg_entry(struct nvkm_bios *, u16 outp, u8 idx,
                      u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
 u16 nvbios_ocfg_parse(struct nvkm_bios *, u16 outp, u8 idx,
                      u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *);
-u16 nvbios_ocfg_match(struct nvkm_bios *, u16 outp, u16 type,
+u16 nvbios_ocfg_match(struct nvkm_bios *, u16 outp, u8 proto, u8 flags,
                      u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *);
 u16 nvbios_oclk_match(struct nvkm_bios *, u16 cmp, u32 khz);
 #endif
index 57aaf98..300ea03 100644 (file)
@@ -552,6 +552,7 @@ nouveau_fbcon_init(struct drm_device *dev)
        if (ret)
                goto fini;
 
+       fbcon->helper.fbdev->pixmap.buf_align = 4;
        return 0;
 
 fini:
index 0f3e4bb..7d9248b 100644 (file)
@@ -82,7 +82,6 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        uint32_t fg;
        uint32_t bg;
        uint32_t dsize;
-       uint32_t width;
        uint32_t *data = (uint32_t *)image->data;
        int ret;
 
@@ -93,9 +92,6 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        if (ret)
                return ret;
 
-       width = ALIGN(image->width, 8);
-       dsize = ALIGN(width * image->height, 32) >> 5;
-
        if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
            info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
                fg = ((uint32_t *) info->pseudo_palette)[image->fg_color];
@@ -111,10 +107,11 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
                         ((image->dx + image->width) & 0xffff));
        OUT_RING(chan, bg);
        OUT_RING(chan, fg);
-       OUT_RING(chan, (image->height << 16) | width);
+       OUT_RING(chan, (image->height << 16) | image->width);
        OUT_RING(chan, (image->height << 16) | image->width);
        OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff));
 
+       dsize = ALIGN(image->width * image->height, 32) >> 5;
        while (dsize) {
                int iter_len = dsize > 128 ? 128 : dsize;
 
index 33d9ee0..1aeb698 100644 (file)
@@ -95,7 +95,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        struct nouveau_fbdev *nfbdev = info->par;
        struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
        struct nouveau_channel *chan = drm->channel;
-       uint32_t width, dwords, *data = (uint32_t *)image->data;
+       uint32_t dwords, *data = (uint32_t *)image->data;
        uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
        uint32_t *palette = info->pseudo_palette;
        int ret;
@@ -107,9 +107,6 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        if (ret)
                return ret;
 
-       width = ALIGN(image->width, 32);
-       dwords = (width * image->height) >> 5;
-
        BEGIN_NV04(chan, NvSub2D, 0x0814, 2);
        if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
            info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -128,6 +125,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        OUT_RING(chan, 0);
        OUT_RING(chan, image->dy);
 
+       dwords = ALIGN(image->width * image->height, 32) >> 5;
        while (dwords) {
                int push = dwords > 2047 ? 2047 : dwords;
 
index a091335..839f4c8 100644 (file)
@@ -95,7 +95,7 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        struct nouveau_fbdev *nfbdev = info->par;
        struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
        struct nouveau_channel *chan = drm->channel;
-       uint32_t width, dwords, *data = (uint32_t *)image->data;
+       uint32_t dwords, *data = (uint32_t *)image->data;
        uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
        uint32_t *palette = info->pseudo_palette;
        int ret;
@@ -107,9 +107,6 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        if (ret)
                return ret;
 
-       width = ALIGN(image->width, 32);
-       dwords = (width * image->height) >> 5;
-
        BEGIN_NVC0(chan, NvSub2D, 0x0814, 2);
        if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
            info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -128,6 +125,7 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        OUT_RING  (chan, 0);
        OUT_RING  (chan, image->dy);
 
+       dwords = ALIGN(image->width * image->height, 32) >> 5;
        while (dwords) {
                int push = dwords > 2047 ? 2047 : dwords;
 
index a74c5dd..e2a64ed 100644 (file)
@@ -18,6 +18,7 @@ nvkm-y += nvkm/engine/disp/piornv50.o
 nvkm-y += nvkm/engine/disp/sornv50.o
 nvkm-y += nvkm/engine/disp/sorg94.o
 nvkm-y += nvkm/engine/disp/sorgf119.o
+nvkm-y += nvkm/engine/disp/sorgm107.o
 nvkm-y += nvkm/engine/disp/sorgm200.o
 nvkm-y += nvkm/engine/disp/dport.o
 
index f031466..5dd3438 100644 (file)
@@ -76,6 +76,7 @@ exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl,
        mask |= 0x0001 << or;
        mask |= 0x0100 << head;
 
+
        list_for_each_entry(outp, &disp->base.outp, head) {
                if ((outp->info.hasht & 0xff) == type &&
                    (outp->info.hashm & mask) == mask) {
@@ -155,25 +156,21 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
        if (!outp)
                return NULL;
 
+       *conf = (ctrl & 0x00000f00) >> 8;
        switch (outp->info.type) {
        case DCB_OUTPUT_TMDS:
-               *conf = (ctrl & 0x00000f00) >> 8;
                if (*conf == 5)
                        *conf |= 0x0100;
                break;
        case DCB_OUTPUT_LVDS:
-               *conf = disp->sor.lvdsconf;
-               break;
-       case DCB_OUTPUT_DP:
-               *conf = (ctrl & 0x00000f00) >> 8;
+               *conf |= disp->sor.lvdsconf;
                break;
-       case DCB_OUTPUT_ANALOG:
        default:
-               *conf = 0x00ff;
                break;
        }
 
-       data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
+       data = nvbios_ocfg_match(bios, data, *conf & 0xff, *conf >> 8,
+                                &ver, &hdr, &cnt, &len, &info2);
        if (data && id < 0xff) {
                data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
                if (data) {
index b694414..f4b9cf8 100644 (file)
@@ -36,7 +36,7 @@ gm107_disp = {
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
        .outp.internal.lvds = nv50_sor_output_new,
-       .outp.internal.dp = gf119_sor_dp_new,
+       .outp.internal.dp = gm107_sor_dp_new,
        .dac.nr = 3,
        .dac.power = nv50_dac_power,
        .dac.sense = nv50_dac_sense,
index 4226d21..fcb1b0c 100644 (file)
@@ -387,22 +387,17 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
        if (!outp)
                return NULL;
 
+       *conf = (ctrl & 0x00000f00) >> 8;
        if (outp->info.location == 0) {
                switch (outp->info.type) {
                case DCB_OUTPUT_TMDS:
-                       *conf = (ctrl & 0x00000f00) >> 8;
                        if (*conf == 5)
                                *conf |= 0x0100;
                        break;
                case DCB_OUTPUT_LVDS:
-                       *conf = disp->sor.lvdsconf;
+                       *conf |= disp->sor.lvdsconf;
                        break;
-               case DCB_OUTPUT_DP:
-                       *conf = (ctrl & 0x00000f00) >> 8;
-                       break;
-               case DCB_OUTPUT_ANALOG:
                default:
-                       *conf = 0x00ff;
                        break;
                }
        } else {
@@ -410,7 +405,8 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
                pclk = pclk / 2;
        }
 
-       data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
+       data = nvbios_ocfg_match(bios, data, *conf & 0xff, *conf >> 8,
+                                &ver, &hdr, &cnt, &len, &info2);
        if (data && id < 0xff) {
                data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
                if (data) {
index e9067ba..4e983f6 100644 (file)
@@ -62,7 +62,12 @@ int g94_sor_dp_lnk_pwr(struct nvkm_output_dp *, int);
 int gf119_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
                     struct nvkm_output **);
 int gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool);
+int gf119_sor_dp_drv_ctl(struct nvkm_output_dp *, int, int, int, int);
 
-int  gm200_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
-                     struct nvkm_output **);
+int gm107_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
+                    struct nvkm_output **);
+int gm107_sor_dp_pattern(struct nvkm_output_dp *, int);
+
+int gm200_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
+                    struct nvkm_output **);
 #endif
index b4b41b1..22706c0 100644 (file)
@@ -40,8 +40,7 @@ static int
 gf119_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
 {
        struct nvkm_device *device = outp->base.disp->engine.subdev.device;
-       const u32 loff = gf119_sor_loff(outp);
-       nvkm_mask(device, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern);
+       nvkm_mask(device, 0x61c110, 0x0f0f0f0f, 0x01010101 * pattern);
        return 0;
 }
 
@@ -64,7 +63,7 @@ gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
        return 0;
 }
 
-static int
+int
 gf119_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
                     int ln, int vs, int pe, int pc)
 {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c
new file mode 100644 (file)
index 0000000..37790b2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+#include "nv50.h"
+#include "outpdp.h"
+
+int
+gm107_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
+{
+       struct nvkm_device *device = outp->base.disp->engine.subdev.device;
+       const u32 soff = outp->base.or * 0x800;
+       const u32 data = 0x01010101 * pattern;
+       if (outp->base.info.sorconf.link & 1)
+               nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, data);
+       else
+               nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data);
+       return 0;
+}
+
+static const struct nvkm_output_dp_func
+gm107_sor_dp_func = {
+       .pattern = gm107_sor_dp_pattern,
+       .lnk_pwr = g94_sor_dp_lnk_pwr,
+       .lnk_ctl = gf119_sor_dp_lnk_ctl,
+       .drv_ctl = gf119_sor_dp_drv_ctl,
+};
+
+int
+gm107_sor_dp_new(struct nvkm_disp *disp, int index,
+                struct dcb_output *dcbE, struct nvkm_output **poutp)
+{
+       return nvkm_output_dp_new_(&gm107_sor_dp_func, disp, index, dcbE, poutp);
+}
index 2cfbef9..c44fa7e 100644 (file)
@@ -56,19 +56,6 @@ gm200_sor_dp_lane_map(struct nvkm_device *device, u8 lane)
        return lane * 0x08;
 }
 
-static int
-gm200_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
-{
-       struct nvkm_device *device = outp->base.disp->engine.subdev.device;
-       const u32 soff = gm200_sor_soff(outp);
-       const u32 data = 0x01010101 * pattern;
-       if (outp->base.info.sorconf.link & 1)
-               nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, data);
-       else
-               nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data);
-       return 0;
-}
-
 static int
 gm200_sor_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
 {
@@ -129,7 +116,7 @@ gm200_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
 
 static const struct nvkm_output_dp_func
 gm200_sor_dp_func = {
-       .pattern = gm200_sor_dp_pattern,
+       .pattern = gm107_sor_dp_pattern,
        .lnk_pwr = gm200_sor_dp_lnk_pwr,
        .lnk_ctl = gf119_sor_dp_lnk_ctl,
        .drv_ctl = gm200_sor_dp_drv_ctl,
index 9513bad..ae9ab5b 100644 (file)
@@ -949,22 +949,41 @@ gf100_gr_trap_gpc_rop(struct gf100_gr *gr, int gpc)
 }
 
 static const struct nvkm_enum gf100_mp_warp_error[] = {
-       { 0x00, "NO_ERROR" },
-       { 0x01, "STACK_MISMATCH" },
+       { 0x01, "STACK_ERROR" },
+       { 0x02, "API_STACK_ERROR" },
+       { 0x03, "RET_EMPTY_STACK_ERROR" },
+       { 0x04, "PC_WRAP" },
        { 0x05, "MISALIGNED_PC" },
-       { 0x08, "MISALIGNED_GPR" },
-       { 0x09, "INVALID_OPCODE" },
-       { 0x0d, "GPR_OUT_OF_BOUNDS" },
-       { 0x0e, "MEM_OUT_OF_BOUNDS" },
-       { 0x0f, "UNALIGNED_MEM_ACCESS" },
+       { 0x06, "PC_OVERFLOW" },
+       { 0x07, "MISALIGNED_IMMC_ADDR" },
+       { 0x08, "MISALIGNED_REG" },
+       { 0x09, "ILLEGAL_INSTR_ENCODING" },
+       { 0x0a, "ILLEGAL_SPH_INSTR_COMBO" },
+       { 0x0b, "ILLEGAL_INSTR_PARAM" },
+       { 0x0c, "INVALID_CONST_ADDR" },
+       { 0x0d, "OOR_REG" },
+       { 0x0e, "OOR_ADDR" },
+       { 0x0f, "MISALIGNED_ADDR" },
        { 0x10, "INVALID_ADDR_SPACE" },
-       { 0x11, "INVALID_PARAM" },
+       { 0x11, "ILLEGAL_INSTR_PARAM2" },
+       { 0x12, "INVALID_CONST_ADDR_LDC" },
+       { 0x13, "GEOMETRY_SM_ERROR" },
+       { 0x14, "DIVERGENT" },
+       { 0x15, "WARP_EXIT" },
        {}
 };
 
 static const struct nvkm_bitfield gf100_mp_global_error[] = {
+       { 0x00000001, "SM_TO_SM_FAULT" },
+       { 0x00000002, "L1_ERROR" },
        { 0x00000004, "MULTIPLE_WARP_ERRORS" },
-       { 0x00000008, "OUT_OF_STACK_SPACE" },
+       { 0x00000008, "PHYSICAL_STACK_OVERFLOW" },
+       { 0x00000010, "BPT_INT" },
+       { 0x00000020, "BPT_PAUSE" },
+       { 0x00000040, "SINGLE_STEP_COMPLETE" },
+       { 0x20000000, "ECC_SEC_ERROR" },
+       { 0x40000000, "ECC_DED_ERROR" },
+       { 0x80000000, "TIMEOUT" },
        {}
 };
 
index a5e9213..9efb1b4 100644 (file)
@@ -141,7 +141,8 @@ nvbios_ocfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx,
 {
        u16 data = nvbios_ocfg_entry(bios, outp, idx, ver, hdr, cnt, len);
        if (data) {
-               info->match     = nvbios_rd16(bios, data + 0x00);
+               info->proto     = nvbios_rd08(bios, data + 0x00);
+               info->flags     = nvbios_rd16(bios, data + 0x01);
                info->clkcmp[0] = nvbios_rd16(bios, data + 0x02);
                info->clkcmp[1] = nvbios_rd16(bios, data + 0x04);
        }
@@ -149,12 +150,13 @@ nvbios_ocfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx,
 }
 
 u16
-nvbios_ocfg_match(struct nvkm_bios *bios, u16 outp, u16 type,
+nvbios_ocfg_match(struct nvkm_bios *bios, u16 outp, u8 proto, u8 flags,
                  u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *info)
 {
        u16 data, idx = 0;
        while ((data = nvbios_ocfg_parse(bios, outp, idx++, ver, hdr, cnt, len, info))) {
-               if (info->match == type)
+               if ((info->proto == proto || info->proto == 0xff) &&
+                   (info->flags == flags))
                        break;
        }
        return data;
index e292f56..389fb13 100644 (file)
@@ -69,11 +69,11 @@ gm107_ltc_zbc_clear_depth(struct nvkm_ltc *ltc, int i, const u32 depth)
 }
 
 static void
-gm107_ltc_lts_isr(struct nvkm_ltc *ltc, int c, int s)
+gm107_ltc_intr_lts(struct nvkm_ltc *ltc, int c, int s)
 {
        struct nvkm_subdev *subdev = &ltc->subdev;
        struct nvkm_device *device = subdev->device;
-       u32 base = 0x140000 + (c * 0x2000) + (s * 0x200);
+       u32 base = 0x140400 + (c * 0x2000) + (s * 0x200);
        u32 stat = nvkm_rd32(device, base + 0x00c);
 
        if (stat) {
@@ -92,7 +92,7 @@ gm107_ltc_intr(struct nvkm_ltc *ltc)
        while (mask) {
                u32 s, c = __ffs(mask);
                for (s = 0; s < ltc->lts_nr; s++)
-                       gm107_ltc_lts_isr(ltc, c, s);
+                       gm107_ltc_intr_lts(ltc, c, s);
                mask &= ~(1 << c);
        }
 }
index 2a29bfd..e18e0dc 100644 (file)
@@ -46,7 +46,7 @@ static const struct nvkm_ltc_func
 gm200_ltc = {
        .oneinit = gm200_ltc_oneinit,
        .init = gm200_ltc_init,
-       .intr = gm107_ltc_intr, /*XXX: not validated */
+       .intr = gm107_ltc_intr,
        .cbc_clear = gm107_ltc_cbc_clear,
        .cbc_wait = gm107_ltc_cbc_wait,
        .zbc = 16,
index 9ed8272..56c43f3 100644 (file)
@@ -1167,7 +1167,6 @@ static int dsi_regulator_init(struct platform_device *dsidev)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        struct regulator *vdds_dsi;
-       int r;
 
        if (dsi->vdds_dsi_reg != NULL)
                return 0;
index e129245..9255c0e 100644 (file)
@@ -120,7 +120,6 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data)
 
 static int hdmi_init_regulator(void)
 {
-       int r;
        struct regulator *reg;
 
        if (hdmi.vdda_reg != NULL)
index 904d075..0f18b76 100644 (file)
@@ -456,14 +456,6 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
 
        WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm.size);
 
-       HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
-                 vc4_state->mm.start);
-
-       if (debug_dump_regs) {
-               DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
-               vc4_hvs_dump_state(dev);
-       }
-
        if (crtc->state->event) {
                unsigned long flags;
 
@@ -473,8 +465,20 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
 
                spin_lock_irqsave(&dev->event_lock, flags);
                vc4_crtc->event = crtc->state->event;
-               spin_unlock_irqrestore(&dev->event_lock, flags);
                crtc->state->event = NULL;
+
+               HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+                         vc4_state->mm.start);
+
+               spin_unlock_irqrestore(&dev->event_lock, flags);
+       } else {
+               HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+                         vc4_state->mm.start);
+       }
+
+       if (debug_dump_regs) {
+               DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
+               vc4_hvs_dump_state(dev);
        }
 }
 
@@ -500,12 +504,17 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
 {
        struct drm_crtc *crtc = &vc4_crtc->base;
        struct drm_device *dev = crtc->dev;
+       struct vc4_dev *vc4 = to_vc4_dev(dev);
+       struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
+       u32 chan = vc4_crtc->channel;
        unsigned long flags;
 
        spin_lock_irqsave(&dev->event_lock, flags);
-       if (vc4_crtc->event) {
+       if (vc4_crtc->event &&
+           (vc4_state->mm.start == HVS_READ(SCALER_DISPLACTX(chan)))) {
                drm_crtc_send_vblank_event(crtc, vc4_crtc->event);
                vc4_crtc->event = NULL;
+               drm_crtc_vblank_put(crtc);
        }
        spin_unlock_irqrestore(&dev->event_lock, flags);
 }
@@ -556,6 +565,7 @@ vc4_async_page_flip_complete(struct vc4_seqno_cb *cb)
                spin_unlock_irqrestore(&dev->event_lock, flags);
        }
 
+       drm_crtc_vblank_put(crtc);
        drm_framebuffer_unreference(flip_state->fb);
        kfree(flip_state);
 
@@ -598,6 +608,8 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
                return ret;
        }
 
+       WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
        /* Immediately update the plane's legacy fb pointer, so that later
         * modeset prep sees the state that will be present when the semaphore
         * is released.
index 3446ece..250ed7e 100644 (file)
@@ -66,12 +66,12 @@ static const struct file_operations vc4_drm_fops = {
 };
 
 static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
-       DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, 0),
-       DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, 0),
-       DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, 0),
-       DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0),
-       DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0),
-       DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, 0),
+       DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(VC4_GET_HANG_STATE, vc4_get_hang_state_ioctl,
                          DRM_ROOT_ONLY),
 };
@@ -91,7 +91,7 @@ static struct drm_driver vc4_drm_driver = {
 
        .enable_vblank = vc4_enable_vblank,
        .disable_vblank = vc4_disable_vblank,
-       .get_vblank_counter = drm_vblank_count,
+       .get_vblank_counter = drm_vblank_no_hw_counter,
 
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = vc4_debugfs_init,
index cb37751..861a623 100644 (file)
@@ -117,10 +117,18 @@ static int vc4_atomic_commit(struct drm_device *dev,
                return -ENOMEM;
 
        /* Make sure that any outstanding modesets have finished. */
-       ret = down_interruptible(&vc4->async_modeset);
-       if (ret) {
-               kfree(c);
-               return ret;
+       if (nonblock) {
+               ret = down_trylock(&vc4->async_modeset);
+               if (ret) {
+                       kfree(c);
+                       return -EBUSY;
+               }
+       } else {
+               ret = down_interruptible(&vc4->async_modeset);
+               if (ret) {
+                       kfree(c);
+                       return ret;
+               }
        }
 
        ret = drm_atomic_helper_prepare_planes(dev, state);
index 6163b95..f99eece 100644 (file)
 #define SCALER_DISPLACT0                        0x00000030
 #define SCALER_DISPLACT1                        0x00000034
 #define SCALER_DISPLACT2                        0x00000038
+#define SCALER_DISPLACTX(x)                    (SCALER_DISPLACT0 +     \
+                                                (x) * (SCALER_DISPLACT1 - \
+                                                       SCALER_DISPLACT0))
+
 #define SCALER_DISPCTRL0                        0x00000040
 # define SCALER_DISPCTRLX_ENABLE               BIT(31)
 # define SCALER_DISPCTRLX_RESET                        BIT(30)
index c2e257d..0409667 100644 (file)
@@ -178,6 +178,7 @@ static int write_gid(struct ib_device *ib_dev, u8 port,
 {
        int ret = 0;
        struct net_device *old_net_dev;
+       enum ib_gid_type old_gid_type;
 
        /* in rdma_cap_roce_gid_table, this funciton should be protected by a
         * sleep-able lock.
@@ -199,6 +200,7 @@ static int write_gid(struct ib_device *ib_dev, u8 port,
        }
 
        old_net_dev = table->data_vec[ix].attr.ndev;
+       old_gid_type = table->data_vec[ix].attr.gid_type;
        if (old_net_dev && old_net_dev != attr->ndev)
                dev_put(old_net_dev);
        /* if modify_gid failed, just delete the old gid */
@@ -207,10 +209,14 @@ static int write_gid(struct ib_device *ib_dev, u8 port,
                attr = &zattr;
                table->data_vec[ix].context = NULL;
        }
-       if (default_gid)
-               table->data_vec[ix].props |= GID_TABLE_ENTRY_DEFAULT;
+
        memcpy(&table->data_vec[ix].gid, gid, sizeof(*gid));
        memcpy(&table->data_vec[ix].attr, attr, sizeof(*attr));
+       if (default_gid) {
+               table->data_vec[ix].props |= GID_TABLE_ENTRY_DEFAULT;
+               if (action == GID_TABLE_WRITE_ACTION_DEL)
+                       table->data_vec[ix].attr.gid_type = old_gid_type;
+       }
        if (table->data_vec[ix].attr.ndev &&
            table->data_vec[ix].attr.ndev != old_net_dev)
                dev_hold(table->data_vec[ix].attr.ndev);
index 1d92e09..c995255 100644 (file)
@@ -3452,14 +3452,14 @@ static int cm_establish(struct ib_cm_id *cm_id)
        work->cm_event.event = IB_CM_USER_ESTABLISHED;
 
        /* Check if the device started its remove_one */
-       spin_lock_irq(&cm.lock);
+       spin_lock_irqsave(&cm.lock, flags);
        if (!cm_dev->going_down) {
                queue_delayed_work(cm.wq, &work->work, 0);
        } else {
                kfree(work);
                ret = -ENODEV;
        }
-       spin_unlock_irq(&cm.lock);
+       spin_unlock_irqrestore(&cm.lock, flags);
 
 out:
        return ret;
index 5516fb0..5c155fa 100644 (file)
@@ -661,6 +661,9 @@ int ib_query_port(struct ib_device *device,
        if (err || port_attr->subnet_prefix)
                return err;
 
+       if (rdma_port_get_link_layer(device, port_num) != IB_LINK_LAYER_INFINIBAND)
+               return 0;
+
        err = ib_query_gid(device, port_num, 0, &gid, NULL);
        if (err)
                return err;
@@ -1024,7 +1027,8 @@ static int __init ib_core_init(void)
                goto err_mad;
        }
 
-       if (ib_add_ibnl_clients()) {
+       ret = ib_add_ibnl_clients();
+       if (ret) {
                pr_warn("Couldn't register ibnl clients\n");
                goto err_sa;
        }
index 43e3fa2..1c41b95 100644 (file)
@@ -506,7 +506,7 @@ int iwpm_add_and_query_mapping_cb(struct sk_buff *skb,
        if (!nlmsg_request) {
                pr_info("%s: Could not find a matching request (seq = %u)\n",
                                 __func__, msg_seq);
-                       return -EINVAL;
+               return -EINVAL;
        }
        pm_msg = nlmsg_request->req_buffer;
        local_sockaddr = (struct sockaddr_storage *)
index 82fb511..2d49228 100644 (file)
@@ -1638,9 +1638,9 @@ static void remove_mad_reg_req(struct ib_mad_agent_private *agent_priv)
                /* Now, check to see if there are any methods still in use */
                if (!check_method_table(method)) {
                        /* If not, release management method table */
-                        kfree(method);
-                        class->method_table[mgmt_class] = NULL;
-                        /* Any management classes left ? */
+                       kfree(method);
+                       class->method_table[mgmt_class] = NULL;
+                       /* Any management classes left ? */
                        if (!check_class_table(class)) {
                                /* If not, release management class table */
                                kfree(class);
index 5e573bb..a5793c8 100644 (file)
@@ -889,9 +889,9 @@ static struct attribute *alloc_hsa_lifespan(char *name, u8 port_num)
 static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
                           u8 port_num)
 {
-       struct attribute_group *hsag = NULL;
+       struct attribute_group *hsag;
        struct rdma_hw_stats *stats;
-       int i = 0, ret;
+       int i, ret;
 
        stats = device->alloc_hw_stats(device, port_num);
 
@@ -899,19 +899,22 @@ static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
                return;
 
        if (!stats->names || stats->num_counters <= 0)
-               goto err;
+               goto err_free_stats;
 
+       /*
+        * Two extra attribue elements here, one for the lifespan entry and
+        * one to NULL terminate the list for the sysfs core code
+        */
        hsag = kzalloc(sizeof(*hsag) +
-                      // 1 extra for the lifespan config entry
-                      sizeof(void *) * (stats->num_counters + 1),
+                      sizeof(void *) * (stats->num_counters + 2),
                       GFP_KERNEL);
        if (!hsag)
-               return;
+               goto err_free_stats;
 
        ret = device->get_hw_stats(device, stats, port_num,
                                   stats->num_counters);
        if (ret != stats->num_counters)
-               goto err;
+               goto err_free_hsag;
 
        stats->timestamp = jiffies;
 
@@ -922,10 +925,13 @@ static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
                hsag->attrs[i] = alloc_hsa(i, port_num, stats->names[i]);
                if (!hsag->attrs[i])
                        goto err;
+               sysfs_attr_init(hsag->attrs[i]);
        }
 
        /* treat an error here as non-fatal */
        hsag->attrs[i] = alloc_hsa_lifespan("lifespan", port_num);
+       if (hsag->attrs[i])
+               sysfs_attr_init(hsag->attrs[i]);
 
        if (port) {
                struct kobject *kobj = &port->kobj;
@@ -946,10 +952,12 @@ static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
        return;
 
 err:
-       kfree(stats);
        for (; i >= 0; i--)
                kfree(hsag->attrs[i]);
+err_free_hsag:
        kfree(hsag);
+err_free_stats:
+       kfree(stats);
        return;
 }
 
index 6e7050a..14d7eeb 100644 (file)
@@ -300,16 +300,15 @@ int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
        const struct cpumask *node_mask,
                *proc_mask = tsk_cpus_allowed(current);
        struct cpu_mask_set *set = &dd->affinity->proc;
-       char buf[1024];
 
        /*
         * check whether process/context affinity has already
         * been set
         */
        if (cpumask_weight(proc_mask) == 1) {
-               scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(proc_mask));
-               hfi1_cdbg(PROC, "PID %u %s affinity set to CPU %s",
-                         current->pid, current->comm, buf);
+               hfi1_cdbg(PROC, "PID %u %s affinity set to CPU %*pbl",
+                         current->pid, current->comm,
+                         cpumask_pr_args(proc_mask));
                /*
                 * Mark the pre-set CPU as used. This is atomic so we don't
                 * need the lock
@@ -318,9 +317,9 @@ int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
                cpumask_set_cpu(cpu, &set->used);
                goto done;
        } else if (cpumask_weight(proc_mask) < cpumask_weight(&set->mask)) {
-               scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(proc_mask));
-               hfi1_cdbg(PROC, "PID %u %s affinity set to CPU set(s) %s",
-                         current->pid, current->comm, buf);
+               hfi1_cdbg(PROC, "PID %u %s affinity set to CPU set(s) %*pbl",
+                         current->pid, current->comm,
+                         cpumask_pr_args(proc_mask));
                goto done;
        }
 
@@ -356,8 +355,8 @@ int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
        cpumask_or(intrs, intrs, (dd->affinity->rcv_intr.gen ?
                                  &dd->affinity->rcv_intr.mask :
                                  &dd->affinity->rcv_intr.used));
-       scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(intrs));
-       hfi1_cdbg(PROC, "CPUs used by interrupts: %s", buf);
+       hfi1_cdbg(PROC, "CPUs used by interrupts: %*pbl",
+                 cpumask_pr_args(intrs));
 
        /*
         * If we don't have a NUMA node requested, preference is towards
@@ -366,18 +365,16 @@ int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
        if (node == -1)
                node = dd->node;
        node_mask = cpumask_of_node(node);
-       scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(node_mask));
-       hfi1_cdbg(PROC, "device on NUMA %u, CPUs %s", node, buf);
+       hfi1_cdbg(PROC, "device on NUMA %u, CPUs %*pbl", node,
+                 cpumask_pr_args(node_mask));
 
        /* diff will hold all unused cpus */
        cpumask_andnot(diff, &set->mask, &set->used);
-       scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(diff));
-       hfi1_cdbg(PROC, "unused CPUs (all) %s", buf);
+       hfi1_cdbg(PROC, "unused CPUs (all) %*pbl", cpumask_pr_args(diff));
 
        /* get cpumask of available CPUs on preferred NUMA */
        cpumask_and(mask, diff, node_mask);
-       scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(mask));
-       hfi1_cdbg(PROC, "available cpus on NUMA %s", buf);
+       hfi1_cdbg(PROC, "available cpus on NUMA %*pbl", cpumask_pr_args(mask));
 
        /*
         * At first, we don't want to place processes on the same
@@ -395,8 +392,8 @@ int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
                cpumask_andnot(diff, &set->mask, &set->used);
                cpumask_andnot(mask, diff, node_mask);
        }
-       scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(mask));
-       hfi1_cdbg(PROC, "possible CPUs for process %s", buf);
+       hfi1_cdbg(PROC, "possible CPUs for process %*pbl",
+                 cpumask_pr_args(mask));
 
        cpu = cpumask_first(mask);
        if (cpu >= nr_cpu_ids) /* empty */
index 3b876da..81619fb 100644 (file)
@@ -7832,8 +7832,8 @@ static void handle_dcc_err(struct hfi1_devdata *dd, u32 unused, u64 reg)
                         * save first 2 flits in the packet that caused
                         * the error
                         */
-                        dd->err_info_rcvport.packet_flit1 = hdr0;
-                        dd->err_info_rcvport.packet_flit2 = hdr1;
+                       dd->err_info_rcvport.packet_flit1 = hdr0;
+                       dd->err_info_rcvport.packet_flit2 = hdr1;
                }
                switch (info) {
                case 1:
@@ -11906,7 +11906,7 @@ static void update_synth_timer(unsigned long opaque)
                hfi1_cdbg(CNTR, "[%d] No update necessary", dd->unit);
        }
 
-mod_timer(&dd->synth_stats_timer, jiffies + HZ * SYNTH_CNT_TIME);
+       mod_timer(&dd->synth_stats_timer, jiffies + HZ * SYNTH_CNT_TIME);
 }
 
 #define C_MAX_NAME 13 /* 12 chars + one for /0 */
index 5cc492e..0d28a5a 100644 (file)
@@ -1337,7 +1337,7 @@ static void cleanup_device_data(struct hfi1_devdata *dd)
                dma_free_coherent(&dd->pcidev->dev, sizeof(u64),
                                  (void *)dd->rcvhdrtail_dummy_kvaddr,
                                  dd->rcvhdrtail_dummy_physaddr);
-                                 dd->rcvhdrtail_dummy_kvaddr = NULL;
+               dd->rcvhdrtail_dummy_kvaddr = NULL;
        }
 
        for (ctxt = 0; tmp && ctxt < dd->num_rcv_contexts; ctxt++) {
index 79b2952..4cfb137 100644 (file)
@@ -214,19 +214,6 @@ const char *print_u32_array(
        return ret;
 }
 
-const char *print_u64_array(
-       struct trace_seq *p,
-       u64 *arr, int len)
-{
-       int i;
-       const char *ret = trace_seq_buffer_ptr(p);
-
-       for (i = 0; i < len; i++)
-               trace_seq_printf(p, "%s0x%016llx", i == 0 ? "" : " ", arr[i]);
-       trace_seq_putc(p, 0);
-       return ret;
-}
-
 __hfi1_trace_fn(PKT);
 __hfi1_trace_fn(PROC);
 __hfi1_trace_fn(SDMA);
index 29f4795..47ffd27 100644 (file)
@@ -183,7 +183,7 @@ struct user_sdma_iovec {
        struct sdma_mmu_node *node;
 };
 
-#define SDMA_CACHE_NODE_EVICT BIT(0)
+#define SDMA_CACHE_NODE_EVICT 0
 
 struct sdma_mmu_node {
        struct mmu_rb_node rb;
@@ -1355,11 +1355,11 @@ static int set_txreq_header(struct user_sdma_request *req,
                 */
                SDMA_DBG(req, "TID offset %ubytes %uunits om%u",
                         req->tidoffset, req->tidoffset / req->omfactor,
-                        !!(req->omfactor - KDETH_OM_SMALL));
+                        req->omfactor != KDETH_OM_SMALL);
                KDETH_SET(hdr->kdeth.ver_tid_offset, OFFSET,
                          req->tidoffset / req->omfactor);
                KDETH_SET(hdr->kdeth.ver_tid_offset, OM,
-                         !!(req->omfactor - KDETH_OM_SMALL));
+                         req->omfactor != KDETH_OM_SMALL);
        }
 done:
        trace_hfi1_sdma_user_header(pq->dd, pq->ctxt, pq->subctxt,
index b01ef6e..0eb09e1 100644 (file)
@@ -505,9 +505,9 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
                        props->device_cap_flags |= IB_DEVICE_MEM_WINDOW_TYPE_2B;
                else
                        props->device_cap_flags |= IB_DEVICE_MEM_WINDOW_TYPE_2A;
-       if (dev->steering_support ==  MLX4_STEERING_MODE_DEVICE_MANAGED)
-               props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING;
        }
+       if (dev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED)
+               props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING;
 
        props->device_cap_flags |= IB_DEVICE_RAW_IP_CSUM;
 
index dabcc65..9c0e67b 100644 (file)
@@ -822,7 +822,8 @@ struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev,
        int eqn;
        int err;
 
-       if (entries < 0)
+       if (entries < 0 ||
+           (entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz))))
                return ERR_PTR(-EINVAL);
 
        if (check_cq_create_flags(attr->flags))
@@ -1168,11 +1169,16 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
                return -ENOSYS;
        }
 
-       if (entries < 1)
+       if (entries < 1 ||
+           entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz))) {
+               mlx5_ib_warn(dev, "wrong entries number %d, max %d\n",
+                            entries,
+                            1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz));
                return -EINVAL;
+       }
 
        entries = roundup_pow_of_two(entries + 1);
-       if (entries >  (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz)) + 1)
+       if (entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz)) + 1)
                return -EINVAL;
 
        if (entries == ibcq->cqe + 1)
index c72797c..b48ad85 100644 (file)
@@ -524,6 +524,9 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
            MLX5_CAP_ETH(dev->mdev, scatter_fcs))
                props->device_cap_flags |= IB_DEVICE_RAW_SCATTER_FCS;
 
+       if (mlx5_get_flow_namespace(dev->mdev, MLX5_FLOW_NAMESPACE_BYPASS))
+               props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING;
+
        props->vendor_part_id      = mdev->pdev->device;
        props->hw_ver              = mdev->pdev->revision;
 
@@ -915,7 +918,8 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        num_uars = req.total_num_uuars / MLX5_NON_FP_BF_REGS_PER_PAGE;
        gross_uuars = num_uars * MLX5_BF_REGS_PER_PAGE;
        resp.qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp);
-       resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size);
+       if (mlx5_core_is_pf(dev->mdev) && MLX5_CAP_GEN(dev->mdev, bf))
+               resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size);
        resp.cache_line_size = L1_CACHE_BYTES;
        resp.max_sq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq);
        resp.max_rq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq);
@@ -988,7 +992,14 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        if (field_avail(typeof(resp), cqe_version, udata->outlen))
                resp.response_length += sizeof(resp.cqe_version);
 
-       if (field_avail(typeof(resp), hca_core_clock_offset, udata->outlen)) {
+       /*
+        * We don't want to expose information from the PCI bar that is located
+        * after 4096 bytes, so if the arch only supports larger pages, let's
+        * pretend we don't support reading the HCA's core clock. This is also
+        * forced by mmap function.
+        */
+       if (PAGE_SIZE <= 4096 &&
+           field_avail(typeof(resp), hca_core_clock_offset, udata->outlen)) {
                resp.comp_mask |=
                        MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_CORE_CLOCK_OFFSET;
                resp.hca_core_clock_offset =
@@ -1798,7 +1809,7 @@ static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
 {
        struct mlx5_ib_dev *dev =
                container_of(device, struct mlx5_ib_dev, ib_dev.dev);
-       return sprintf(buf, "%d.%d.%d\n", fw_rev_maj(dev->mdev),
+       return sprintf(buf, "%d.%d.%04d\n", fw_rev_maj(dev->mdev),
                       fw_rev_min(dev->mdev), fw_rev_sub(dev->mdev));
 }
 
@@ -1866,14 +1877,11 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
                break;
 
        case MLX5_DEV_EVENT_PORT_DOWN:
+       case MLX5_DEV_EVENT_PORT_INITIALIZED:
                ibev.event = IB_EVENT_PORT_ERR;
                port = (u8)param;
                break;
 
-       case MLX5_DEV_EVENT_PORT_INITIALIZED:
-               /* not used by ULPs */
-               return;
-
        case MLX5_DEV_EVENT_LID_CHANGE:
                ibev.event = IB_EVENT_LID_CHANGE;
                port = (u8)param;
index 5041176..ce43422 100644 (file)
@@ -235,6 +235,8 @@ static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap,
                qp->rq.max_gs = 0;
                qp->rq.wqe_cnt = 0;
                qp->rq.wqe_shift = 0;
+               cap->max_recv_wr = 0;
+               cap->max_recv_sge = 0;
        } else {
                if (ucmd) {
                        qp->rq.wqe_cnt = ucmd->rq_wqe_count;
@@ -1851,13 +1853,15 @@ static int modify_raw_packet_eth_prio(struct mlx5_core_dev *dev,
 static int mlx5_set_path(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
                         const struct ib_ah_attr *ah,
                         struct mlx5_qp_path *path, u8 port, int attr_mask,
-                        u32 path_flags, const struct ib_qp_attr *attr)
+                        u32 path_flags, const struct ib_qp_attr *attr,
+                        bool alt)
 {
        enum rdma_link_layer ll = rdma_port_get_link_layer(&dev->ib_dev, port);
        int err;
 
        if (attr_mask & IB_QP_PKEY_INDEX)
-               path->pkey_index = attr->pkey_index;
+               path->pkey_index = cpu_to_be16(alt ? attr->alt_pkey_index :
+                                                    attr->pkey_index);
 
        if (ah->ah_flags & IB_AH_GRH) {
                if (ah->grh.sgid_index >=
@@ -1877,9 +1881,9 @@ static int mlx5_set_path(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
                                                          ah->grh.sgid_index);
                path->dci_cfi_prio_sl = (ah->sl & 0x7) << 4;
        } else {
-               path->fl = (path_flags & MLX5_PATH_FLAG_FL) ? 0x80 : 0;
-               path->free_ar = (path_flags & MLX5_PATH_FLAG_FREE_AR) ? 0x80 :
-                                                                       0;
+               path->fl_free_ar = (path_flags & MLX5_PATH_FLAG_FL) ? 0x80 : 0;
+               path->fl_free_ar |=
+                       (path_flags & MLX5_PATH_FLAG_FREE_AR) ? 0x40 : 0;
                path->rlid = cpu_to_be16(ah->dlid);
                path->grh_mlid = ah->src_path_bits & 0x7f;
                if (ah->ah_flags & IB_AH_GRH)
@@ -1903,7 +1907,7 @@ static int mlx5_set_path(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
        path->port = port;
 
        if (attr_mask & IB_QP_TIMEOUT)
-               path->ackto_lt = attr->timeout << 3;
+               path->ackto_lt = (alt ? attr->alt_timeout : attr->timeout) << 3;
 
        if ((qp->ibqp.qp_type == IB_QPT_RAW_PACKET) && qp->sq.wqe_cnt)
                return modify_raw_packet_eth_prio(dev->mdev,
@@ -2264,7 +2268,7 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
                context->log_pg_sz_remote_qpn = cpu_to_be32(attr->dest_qp_num);
 
        if (attr_mask & IB_QP_PKEY_INDEX)
-               context->pri_path.pkey_index = attr->pkey_index;
+               context->pri_path.pkey_index = cpu_to_be16(attr->pkey_index);
 
        /* todo implement counter_index functionality */
 
@@ -2277,7 +2281,7 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
        if (attr_mask & IB_QP_AV) {
                err = mlx5_set_path(dev, qp, &attr->ah_attr, &context->pri_path,
                                    attr_mask & IB_QP_PORT ? attr->port_num : qp->port,
-                                   attr_mask, 0, attr);
+                                   attr_mask, 0, attr, false);
                if (err)
                        goto out;
        }
@@ -2288,7 +2292,9 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
        if (attr_mask & IB_QP_ALT_PATH) {
                err = mlx5_set_path(dev, qp, &attr->alt_ah_attr,
                                    &context->alt_path,
-                                   attr->alt_port_num, attr_mask, 0, attr);
+                                   attr->alt_port_num,
+                                   attr_mask | IB_QP_PKEY_INDEX | IB_QP_TIMEOUT,
+                                   0, attr, true);
                if (err)
                        goto out;
        }
@@ -4013,11 +4019,12 @@ static int query_qp_attr(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
        if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) {
                to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
                to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
-               qp_attr->alt_pkey_index = context->alt_path.pkey_index & 0x7f;
+               qp_attr->alt_pkey_index =
+                       be16_to_cpu(context->alt_path.pkey_index);
                qp_attr->alt_port_num   = qp_attr->alt_ah_attr.port_num;
        }
 
-       qp_attr->pkey_index = context->pri_path.pkey_index & 0x7f;
+       qp_attr->pkey_index = be16_to_cpu(context->pri_path.pkey_index);
        qp_attr->port_num = context->pri_path.port;
 
        /* qp_attr->en_sqd_async_notify is only applicable in modify qp */
@@ -4079,17 +4086,19 @@ int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
        qp_attr->cap.max_recv_sge    = qp->rq.max_gs;
 
        if (!ibqp->uobject) {
-               qp_attr->cap.max_send_wr  = qp->sq.wqe_cnt;
+               qp_attr->cap.max_send_wr  = qp->sq.max_post;
                qp_attr->cap.max_send_sge = qp->sq.max_gs;
+               qp_init_attr->qp_context = ibqp->qp_context;
        } else {
                qp_attr->cap.max_send_wr  = 0;
                qp_attr->cap.max_send_sge = 0;
        }
 
-       /* We don't support inline sends for kernel QPs (yet), and we
-        * don't know what userspace's value should be.
-        */
-       qp_attr->cap.max_inline_data = 0;
+       qp_init_attr->qp_type = ibqp->qp_type;
+       qp_init_attr->recv_cq = ibqp->recv_cq;
+       qp_init_attr->send_cq = ibqp->send_cq;
+       qp_init_attr->srq = ibqp->srq;
+       qp_attr->cap.max_inline_data = qp->max_inline_data;
 
        qp_init_attr->cap            = qp_attr->cap;
 
index 7209fbc..a0b6ebe 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/sched.h>
 #include <linux/hugetlb.h>
-#include <linux/dma-attrs.h>
 #include <linux/iommu.h>
 #include <linux/workqueue.h>
 #include <linux/list.h>
@@ -112,10 +111,6 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
        int i;
        int flags;
        dma_addr_t pa;
-       DEFINE_DMA_ATTRS(attrs);
-
-       if (dmasync)
-               dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
 
        if (!can_do_mlock())
                return -EPERM;
index 5fa4d4d..7de5134 100644 (file)
@@ -502,6 +502,12 @@ static void rvt_remove_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp)
  */
 static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
                  enum ib_qp_type type)
+       __releases(&qp->s_lock)
+       __releases(&qp->s_hlock)
+       __releases(&qp->r_lock)
+       __acquires(&qp->r_lock)
+       __acquires(&qp->s_hlock)
+       __acquires(&qp->s_lock)
 {
        if (qp->state != IB_QPS_RESET) {
                qp->state = IB_QPS_RESET;
index bab7db6..4f7d9b4 100644 (file)
@@ -94,6 +94,7 @@ enum {
        IPOIB_NEIGH_TBL_FLUSH     = 12,
        IPOIB_FLAG_DEV_ADDR_SET   = 13,
        IPOIB_FLAG_DEV_ADDR_CTRL  = 14,
+       IPOIB_FLAG_GOING_DOWN     = 15,
 
        IPOIB_MAX_BACKOFF_SECONDS = 16,
 
index b2f4283..951d9ab 100644 (file)
@@ -1486,6 +1486,10 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
 {
        struct net_device *dev = to_net_dev(d);
        int ret;
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+
+       if (test_bit(IPOIB_FLAG_GOING_DOWN, &priv->flags))
+               return -EPERM;
 
        if (!rtnl_trylock())
                return restart_syscall();
index 45c40a1..dc6d241 100644 (file)
@@ -1015,7 +1015,7 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv)
        if (ib_query_gid(priv->ca, priv->port, 0, &gid0, NULL))
                return false;
 
-       netif_addr_lock(priv->dev);
+       netif_addr_lock_bh(priv->dev);
 
        /* The subnet prefix may have changed, update it now so we won't have
         * to do it later
@@ -1026,12 +1026,12 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv)
 
        search_gid.global.interface_id = priv->local_gid.global.interface_id;
 
-       netif_addr_unlock(priv->dev);
+       netif_addr_unlock_bh(priv->dev);
 
        err = ib_find_gid(priv->ca, &search_gid, IB_GID_TYPE_IB,
                          priv->dev, &port, &index);
 
-       netif_addr_lock(priv->dev);
+       netif_addr_lock_bh(priv->dev);
 
        if (search_gid.global.interface_id !=
            priv->local_gid.global.interface_id)
@@ -1092,7 +1092,7 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv)
        }
 
 out:
-       netif_addr_unlock(priv->dev);
+       netif_addr_unlock_bh(priv->dev);
 
        return ret;
 }
index 2d7c163..5f58c41 100644 (file)
@@ -1206,7 +1206,9 @@ struct ipoib_neigh *ipoib_neigh_get(struct net_device *dev, u8 *daddr)
                                neigh = NULL;
                                goto out_unlock;
                        }
-                       neigh->alive = jiffies;
+
+                       if (likely(skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE))
+                               neigh->alive = jiffies;
                        goto out_unlock;
                }
        }
@@ -1851,7 +1853,7 @@ static void set_base_guid(struct ipoib_dev_priv *priv, union ib_gid *gid)
        struct ipoib_dev_priv *child_priv;
        struct net_device *netdev = priv->dev;
 
-       netif_addr_lock(netdev);
+       netif_addr_lock_bh(netdev);
 
        memcpy(&priv->local_gid.global.interface_id,
               &gid->global.interface_id,
@@ -1859,7 +1861,7 @@ static void set_base_guid(struct ipoib_dev_priv *priv, union ib_gid *gid)
        memcpy(netdev->dev_addr + 4, &priv->local_gid, sizeof(priv->local_gid));
        clear_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags);
 
-       netif_addr_unlock(netdev);
+       netif_addr_unlock_bh(netdev);
 
        if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
                down_read(&priv->vlan_rwsem);
@@ -1875,7 +1877,7 @@ static int ipoib_check_lladdr(struct net_device *dev,
        union ib_gid *gid = (union ib_gid *)(ss->__data + 4);
        int ret = 0;
 
-       netif_addr_lock(dev);
+       netif_addr_lock_bh(dev);
 
        /* Make sure the QPN, reserved and subnet prefix match the current
         * lladdr, it also makes sure the lladdr is unicast.
@@ -1885,7 +1887,7 @@ static int ipoib_check_lladdr(struct net_device *dev,
            gid->global.interface_id == 0)
                ret = -EINVAL;
 
-       netif_addr_unlock(dev);
+       netif_addr_unlock_bh(dev);
 
        return ret;
 }
@@ -2141,6 +2143,9 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data)
                ib_unregister_event_handler(&priv->event_handler);
                flush_workqueue(ipoib_workqueue);
 
+               /* mark interface in the middle of destruction */
+               set_bit(IPOIB_FLAG_GOING_DOWN, &priv->flags);
+
                rtnl_lock();
                dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP);
                rtnl_unlock();
index 82fbc94..d3394b6 100644 (file)
@@ -582,13 +582,13 @@ void ipoib_mcast_join_task(struct work_struct *work)
                return;
        }
        priv->local_lid = port_attr.lid;
-       netif_addr_lock(dev);
+       netif_addr_lock_bh(dev);
 
        if (!test_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags)) {
-               netif_addr_unlock(dev);
+               netif_addr_unlock_bh(dev);
                return;
        }
-       netif_addr_unlock(dev);
+       netif_addr_unlock_bh(dev);
 
        spin_lock_irq(&priv->lock);
        if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
index 64a3559..a2f9f29 100644 (file)
@@ -131,6 +131,9 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
 
        ppriv = netdev_priv(pdev);
 
+       if (test_bit(IPOIB_FLAG_GOING_DOWN, &ppriv->flags))
+               return -EPERM;
+
        snprintf(intf_name, sizeof intf_name, "%s.%04x",
                 ppriv->dev->name, pkey);
        priv = ipoib_intf_alloc(intf_name);
@@ -183,6 +186,9 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
 
        ppriv = netdev_priv(pdev);
 
+       if (test_bit(IPOIB_FLAG_GOING_DOWN, &ppriv->flags))
+               return -EPERM;
+
        if (!rtnl_trylock())
                return restart_syscall();
 
index 646de17..3322ed7 100644 (file)
@@ -1457,7 +1457,6 @@ static int srp_map_sg_fr(struct srp_map_state *state, struct srp_rdma_ch *ch,
 {
        unsigned int sg_offset = 0;
 
-       state->desc = req->indirect_desc;
        state->fr.next = req->fr_list;
        state->fr.end = req->fr_list + ch->target->mr_per_cmd;
        state->sg = scat;
@@ -1489,7 +1488,6 @@ static int srp_map_sg_dma(struct srp_map_state *state, struct srp_rdma_ch *ch,
        struct scatterlist *sg;
        int i;
 
-       state->desc = req->indirect_desc;
        for_each_sg(scat, sg, count, i) {
                srp_map_desc(state, ib_sg_dma_address(dev->dev, sg),
                             ib_sg_dma_len(dev->dev, sg),
@@ -1655,6 +1653,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
                                   target->indirect_size, DMA_TO_DEVICE);
 
        memset(&state, 0, sizeof(state));
+       state.desc = req->indirect_desc;
        if (dev->use_fast_reg)
                ret = srp_map_sg_fr(&state, ch, req, scat, count);
        else if (dev->use_fmr)
@@ -3526,7 +3525,7 @@ static void srp_add_one(struct ib_device *device)
        int mr_page_shift, p;
        u64 max_pages_per_mr;
 
-       srp_dev = kmalloc(sizeof *srp_dev, GFP_KERNEL);
+       srp_dev = kzalloc(sizeof(*srp_dev), GFP_KERNEL);
        if (!srp_dev)
                return;
 
@@ -3586,8 +3585,6 @@ static void srp_add_one(struct ib_device *device)
                                                   IB_ACCESS_REMOTE_WRITE);
                if (IS_ERR(srp_dev->global_mr))
                        goto err_pd;
-       } else {
-               srp_dev->global_mr = NULL;
        }
 
        for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) {
index c5fe915..a59d55e 100644 (file)
@@ -12895,52 +12895,71 @@ static int __bnx2x_vlan_configure_vid(struct bnx2x *bp, u16 vid, bool add)
        return rc;
 }
 
-int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp)
+static int bnx2x_vlan_configure_vid_list(struct bnx2x *bp)
 {
        struct bnx2x_vlan_entry *vlan;
        int rc = 0;
 
-       if (!bp->vlan_cnt) {
-               DP(NETIF_MSG_IFUP, "No need to re-configure vlan filters\n");
-               return 0;
-       }
-
+       /* Configure all non-configured entries */
        list_for_each_entry(vlan, &bp->vlan_reg, link) {
-               /* Prepare for cleanup in case of errors */
-               if (rc) {
-                       vlan->hw = false;
-                       continue;
-               }
-
-               if (!vlan->hw)
+               if (vlan->hw)
                        continue;
 
-               DP(NETIF_MSG_IFUP, "Re-configuring vlan 0x%04x\n", vlan->vid);
+               if (bp->vlan_cnt >= bp->vlan_credit)
+                       return -ENOBUFS;
 
                rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true);
                if (rc) {
-                       BNX2X_ERR("Unable to configure VLAN %d\n", vlan->vid);
-                       vlan->hw = false;
-                       rc = -EINVAL;
-                       continue;
+                       BNX2X_ERR("Unable to config VLAN %d\n", vlan->vid);
+                       return rc;
                }
+
+               DP(NETIF_MSG_IFUP, "HW configured for VLAN %d\n", vlan->vid);
+               vlan->hw = true;
+               bp->vlan_cnt++;
        }
 
-       return rc;
+       return 0;
+}
+
+static void bnx2x_vlan_configure(struct bnx2x *bp, bool set_rx_mode)
+{
+       bool need_accept_any_vlan;
+
+       need_accept_any_vlan = !!bnx2x_vlan_configure_vid_list(bp);
+
+       if (bp->accept_any_vlan != need_accept_any_vlan) {
+               bp->accept_any_vlan = need_accept_any_vlan;
+               DP(NETIF_MSG_IFUP, "Accept all VLAN %s\n",
+                  bp->accept_any_vlan ? "raised" : "cleared");
+               if (set_rx_mode) {
+                       if (IS_PF(bp))
+                               bnx2x_set_rx_mode_inner(bp);
+                       else
+                               bnx2x_vfpf_storm_rx_mode(bp);
+               }
+       }
+}
+
+int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp)
+{
+       struct bnx2x_vlan_entry *vlan;
+
+       /* The hw forgot all entries after reload */
+       list_for_each_entry(vlan, &bp->vlan_reg, link)
+               vlan->hw = false;
+       bp->vlan_cnt = 0;
+
+       /* Don't set rx mode here. Our caller will do it. */
+       bnx2x_vlan_configure(bp, false);
+
+       return 0;
 }
 
 static int bnx2x_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
 {
        struct bnx2x *bp = netdev_priv(dev);
        struct bnx2x_vlan_entry *vlan;
-       bool hw = false;
-       int rc = 0;
-
-       if (!netif_running(bp->dev)) {
-               DP(NETIF_MSG_IFUP,
-                  "Ignoring VLAN configuration the interface is down\n");
-               return -EFAULT;
-       }
 
        DP(NETIF_MSG_IFUP, "Adding VLAN %d\n", vid);
 
@@ -12948,93 +12967,47 @@ static int bnx2x_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
        if (!vlan)
                return -ENOMEM;
 
-       bp->vlan_cnt++;
-       if (bp->vlan_cnt > bp->vlan_credit && !bp->accept_any_vlan) {
-               DP(NETIF_MSG_IFUP, "Accept all VLAN raised\n");
-               bp->accept_any_vlan = true;
-               if (IS_PF(bp))
-                       bnx2x_set_rx_mode_inner(bp);
-               else
-                       bnx2x_vfpf_storm_rx_mode(bp);
-       } else if (bp->vlan_cnt <= bp->vlan_credit) {
-               rc = __bnx2x_vlan_configure_vid(bp, vid, true);
-               hw = true;
-       }
-
        vlan->vid = vid;
-       vlan->hw = hw;
+       vlan->hw = false;
+       list_add_tail(&vlan->link, &bp->vlan_reg);
 
-       if (!rc) {
-               list_add(&vlan->link, &bp->vlan_reg);
-       } else {
-               bp->vlan_cnt--;
-               kfree(vlan);
-       }
-
-       DP(NETIF_MSG_IFUP, "Adding VLAN result %d\n", rc);
+       if (netif_running(dev))
+               bnx2x_vlan_configure(bp, true);
 
-       return rc;
+       return 0;
 }
 
 static int bnx2x_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
 {
        struct bnx2x *bp = netdev_priv(dev);
        struct bnx2x_vlan_entry *vlan;
+       bool found = false;
        int rc = 0;
 
-       if (!netif_running(bp->dev)) {
-               DP(NETIF_MSG_IFUP,
-                  "Ignoring VLAN configuration the interface is down\n");
-               return -EFAULT;
-       }
-
        DP(NETIF_MSG_IFUP, "Removing VLAN %d\n", vid);
 
-       if (!bp->vlan_cnt) {
-               BNX2X_ERR("Unable to kill VLAN %d\n", vid);
-               return -EINVAL;
-       }
-
        list_for_each_entry(vlan, &bp->vlan_reg, link)
-               if (vlan->vid == vid)
+               if (vlan->vid == vid) {
+                       found = true;
                        break;
+               }
 
-       if (vlan->vid != vid) {
+       if (!found) {
                BNX2X_ERR("Unable to kill VLAN %d - not found\n", vid);
                return -EINVAL;
        }
 
-       if (vlan->hw)
+       if (netif_running(dev) && vlan->hw) {
                rc = __bnx2x_vlan_configure_vid(bp, vid, false);
+               DP(NETIF_MSG_IFUP, "HW deconfigured for VLAN %d\n", vid);
+               bp->vlan_cnt--;
+       }
 
        list_del(&vlan->link);
        kfree(vlan);
 
-       bp->vlan_cnt--;
-
-       if (bp->vlan_cnt <= bp->vlan_credit && bp->accept_any_vlan) {
-               /* Configure all non-configured entries */
-               list_for_each_entry(vlan, &bp->vlan_reg, link) {
-                       if (vlan->hw)
-                               continue;
-
-                       rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true);
-                       if (rc) {
-                               BNX2X_ERR("Unable to config VLAN %d\n",
-                                         vlan->vid);
-                               continue;
-                       }
-                       DP(NETIF_MSG_IFUP, "HW configured for VLAN %d\n",
-                          vlan->vid);
-                       vlan->hw = true;
-               }
-               DP(NETIF_MSG_IFUP, "Accept all VLAN Removed\n");
-               bp->accept_any_vlan = false;
-               if (IS_PF(bp))
-                       bnx2x_set_rx_mode_inner(bp);
-               else
-                       bnx2x_vfpf_storm_rx_mode(bp);
-       }
+       if (netif_running(dev))
+               bnx2x_vlan_configure(bp, true);
 
        DP(NETIF_MSG_IFUP, "Removing VLAN result %d\n", rc);
 
index 72a2eff..c777cde 100644 (file)
@@ -286,7 +286,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        cpu_to_le32(DB_KEY_TX_PUSH | DB_LONG_TX_PUSH | prod);
                txr->tx_prod = prod;
 
+               tx_buf->is_push = 1;
                netdev_tx_sent_queue(txq, skb->len);
+               wmb();  /* Sync is_push and byte queue before pushing data */
 
                push_len = (length + sizeof(*tx_push) + 7) / 8;
                if (push_len > 16) {
@@ -298,7 +300,6 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                         push_len);
                }
 
-               tx_buf->is_push = 1;
                goto tx_done;
        }
 
@@ -1112,19 +1113,13 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
        if (tpa_info->hash_type != PKT_HASH_TYPE_NONE)
                skb_set_hash(skb, tpa_info->rss_hash, tpa_info->hash_type);
 
-       if (tpa_info->flags2 & RX_CMP_FLAGS2_META_FORMAT_VLAN) {
-               netdev_features_t features = skb->dev->features;
+       if ((tpa_info->flags2 & RX_CMP_FLAGS2_META_FORMAT_VLAN) &&
+           (skb->dev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
                u16 vlan_proto = tpa_info->metadata >>
                        RX_CMP_FLAGS2_METADATA_TPID_SFT;
+               u16 vtag = tpa_info->metadata & RX_CMP_FLAGS2_METADATA_VID_MASK;
 
-               if (((features & NETIF_F_HW_VLAN_CTAG_RX) &&
-                    vlan_proto == ETH_P_8021Q) ||
-                   ((features & NETIF_F_HW_VLAN_STAG_RX) &&
-                    vlan_proto == ETH_P_8021AD)) {
-                       __vlan_hwaccel_put_tag(skb, htons(vlan_proto),
-                                              tpa_info->metadata &
-                                              RX_CMP_FLAGS2_METADATA_VID_MASK);
-               }
+               __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vtag);
        }
 
        skb_checksum_none_assert(skb);
@@ -1277,19 +1272,14 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
 
        skb->protocol = eth_type_trans(skb, dev);
 
-       if (rxcmp1->rx_cmp_flags2 &
-           cpu_to_le32(RX_CMP_FLAGS2_META_FORMAT_VLAN)) {
-               netdev_features_t features = skb->dev->features;
+       if ((rxcmp1->rx_cmp_flags2 &
+            cpu_to_le32(RX_CMP_FLAGS2_META_FORMAT_VLAN)) &&
+           (skb->dev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
                u32 meta_data = le32_to_cpu(rxcmp1->rx_cmp_meta_data);
+               u16 vtag = meta_data & RX_CMP_FLAGS2_METADATA_VID_MASK;
                u16 vlan_proto = meta_data >> RX_CMP_FLAGS2_METADATA_TPID_SFT;
 
-               if (((features & NETIF_F_HW_VLAN_CTAG_RX) &&
-                    vlan_proto == ETH_P_8021Q) ||
-                   ((features & NETIF_F_HW_VLAN_STAG_RX) &&
-                    vlan_proto == ETH_P_8021AD))
-                       __vlan_hwaccel_put_tag(skb, htons(vlan_proto),
-                                              meta_data &
-                                              RX_CMP_FLAGS2_METADATA_VID_MASK);
+               __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vtag);
        }
 
        skb_checksum_none_assert(skb);
@@ -5466,6 +5456,20 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 
        if (!bnxt_rfs_capable(bp))
                features &= ~NETIF_F_NTUPLE;
+
+       /* Both CTAG and STAG VLAN accelaration on the RX side have to be
+        * turned on or off together.
+        */
+       if ((features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) !=
+           (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) {
+               if (dev->features & NETIF_F_HW_VLAN_CTAG_RX)
+                       features &= ~(NETIF_F_HW_VLAN_CTAG_RX |
+                                     NETIF_F_HW_VLAN_STAG_RX);
+               else
+                       features |= NETIF_F_HW_VLAN_CTAG_RX |
+                                   NETIF_F_HW_VLAN_STAG_RX;
+       }
+
        return features;
 }
 
index a2cdfc1..50812a1 100644 (file)
@@ -144,6 +144,7 @@ CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN
        CH_PCI_ID_TABLE_FENTRY(0x5015), /* T502-bt */
        CH_PCI_ID_TABLE_FENTRY(0x5016), /* T580-OCP-SO */
        CH_PCI_ID_TABLE_FENTRY(0x5017), /* T520-OCP-SO */
+       CH_PCI_ID_TABLE_FENTRY(0x5018), /* T540-BT */
        CH_PCI_ID_TABLE_FENTRY(0x5080), /* Custom T540-cr */
        CH_PCI_ID_TABLE_FENTRY(0x5081), /* Custom T540-LL-cr */
        CH_PCI_ID_TABLE_FENTRY(0x5082), /* Custom T504-cr */
index 41b0106..4edb98c 100644 (file)
@@ -1195,7 +1195,7 @@ static int ethoc_probe(struct platform_device *pdev)
        priv->mdio = mdiobus_alloc();
        if (!priv->mdio) {
                ret = -ENOMEM;
-               goto free;
+               goto free2;
        }
 
        priv->mdio->name = "ethoc-mdio";
@@ -1208,7 +1208,7 @@ static int ethoc_probe(struct platform_device *pdev)
        ret = mdiobus_register(priv->mdio);
        if (ret) {
                dev_err(&netdev->dev, "failed to register MDIO bus\n");
-               goto free;
+               goto free2;
        }
 
        ret = ethoc_mdio_probe(netdev);
@@ -1241,9 +1241,10 @@ error2:
 error:
        mdiobus_unregister(priv->mdio);
        mdiobus_free(priv->mdio);
-free:
+free2:
        if (priv->clk)
                clk_disable_unprepare(priv->clk);
+free:
        free_netdev(netdev);
 out:
        return ret;
index 3c0255e..fea0f33 100644 (file)
@@ -2416,24 +2416,24 @@ fec_enet_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec)
                return -EOPNOTSUPP;
 
        if (ec->rx_max_coalesced_frames > 255) {
-               pr_err("Rx coalesced frames exceed hardware limiation");
+               pr_err("Rx coalesced frames exceed hardware limitation\n");
                return -EINVAL;
        }
 
        if (ec->tx_max_coalesced_frames > 255) {
-               pr_err("Tx coalesced frame exceed hardware limiation");
+               pr_err("Tx coalesced frame exceed hardware limitation\n");
                return -EINVAL;
        }
 
        cycle = fec_enet_us_to_itr_clock(ndev, fep->rx_time_itr);
        if (cycle > 0xFFFF) {
-               pr_err("Rx coalesed usec exceeed hardware limiation");
+               pr_err("Rx coalesced usec exceed hardware limitation\n");
                return -EINVAL;
        }
 
        cycle = fec_enet_us_to_itr_clock(ndev, fep->tx_time_itr);
        if (cycle > 0xFFFF) {
-               pr_err("Rx coalesed usec exceeed hardware limiation");
+               pr_err("Rx coalesced usec exceed hardware limitation\n");
                return -EINVAL;
        }
 
index 7615e06..2e6785b 100644 (file)
@@ -2440,7 +2440,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                                 tx_queue->tx_ring_size);
 
        if (likely(!nr_frags)) {
-               lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
+               if (likely(!do_tstamp))
+                       lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
        } else {
                u32 lstatus_start = lstatus;
 
index c984462..4763252 100644 (file)
@@ -133,6 +133,8 @@ static int mtk_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
 static void mtk_phy_link_adjust(struct net_device *dev)
 {
        struct mtk_mac *mac = netdev_priv(dev);
+       u16 lcl_adv = 0, rmt_adv = 0;
+       u8 flowctrl;
        u32 mcr = MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG |
                  MAC_MCR_FORCE_MODE | MAC_MCR_TX_EN |
                  MAC_MCR_RX_EN | MAC_MCR_BACKOFF_EN |
@@ -150,11 +152,30 @@ static void mtk_phy_link_adjust(struct net_device *dev)
        if (mac->phy_dev->link)
                mcr |= MAC_MCR_FORCE_LINK;
 
-       if (mac->phy_dev->duplex)
+       if (mac->phy_dev->duplex) {
                mcr |= MAC_MCR_FORCE_DPX;
 
-       if (mac->phy_dev->pause)
-               mcr |= MAC_MCR_FORCE_RX_FC | MAC_MCR_FORCE_TX_FC;
+               if (mac->phy_dev->pause)
+                       rmt_adv = LPA_PAUSE_CAP;
+               if (mac->phy_dev->asym_pause)
+                       rmt_adv |= LPA_PAUSE_ASYM;
+
+               if (mac->phy_dev->advertising & ADVERTISED_Pause)
+                       lcl_adv |= ADVERTISE_PAUSE_CAP;
+               if (mac->phy_dev->advertising & ADVERTISED_Asym_Pause)
+                       lcl_adv |= ADVERTISE_PAUSE_ASYM;
+
+               flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+
+               if (flowctrl & FLOW_CTRL_TX)
+                       mcr |= MAC_MCR_FORCE_TX_FC;
+               if (flowctrl & FLOW_CTRL_RX)
+                       mcr |= MAC_MCR_FORCE_RX_FC;
+
+               netif_dbg(mac->hw, link, dev, "rx pause %s, tx pause %s\n",
+                         flowctrl & FLOW_CTRL_RX ? "enabled" : "disabled",
+                         flowctrl & FLOW_CTRL_TX ? "enabled" : "disabled");
+       }
 
        mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
 
@@ -208,10 +229,16 @@ static int mtk_phy_connect(struct mtk_mac *mac)
        u32 val, ge_mode;
 
        np = of_parse_phandle(mac->of_node, "phy-handle", 0);
+       if (!np && of_phy_is_fixed_link(mac->of_node))
+               if (!of_phy_register_fixed_link(mac->of_node))
+                       np = of_node_get(mac->of_node);
        if (!np)
                return -ENODEV;
 
        switch (of_get_phy_mode(np)) {
+       case PHY_INTERFACE_MODE_RGMII_TXID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+       case PHY_INTERFACE_MODE_RGMII_ID:
        case PHY_INTERFACE_MODE_RGMII:
                ge_mode = 0;
                break;
@@ -236,7 +263,8 @@ static int mtk_phy_connect(struct mtk_mac *mac)
        mac->phy_dev->autoneg = AUTONEG_ENABLE;
        mac->phy_dev->speed = 0;
        mac->phy_dev->duplex = 0;
-       mac->phy_dev->supported &= PHY_BASIC_FEATURES;
+       mac->phy_dev->supported &= PHY_GBIT_FEATURES | SUPPORTED_Pause |
+                                  SUPPORTED_Asym_Pause;
        mac->phy_dev->advertising = mac->phy_dev->supported |
                                    ADVERTISED_Autoneg;
        phy_start_aneg(mac->phy_dev);
@@ -280,7 +308,7 @@ static int mtk_mdio_init(struct mtk_eth *eth)
        return 0;
 
 err_free_bus:
-       kfree(eth->mii_bus);
+       mdiobus_free(eth->mii_bus);
 
 err_put_node:
        of_node_put(mii_np);
@@ -295,7 +323,7 @@ static void mtk_mdio_cleanup(struct mtk_eth *eth)
 
        mdiobus_unregister(eth->mii_bus);
        of_node_put(eth->mii_bus->dev.of_node);
-       kfree(eth->mii_bus);
+       mdiobus_free(eth->mii_bus);
 }
 
 static inline void mtk_irq_disable(struct mtk_eth *eth, u32 mask)
index fd43929..f5c8d5d 100644 (file)
@@ -3192,10 +3192,7 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv)
        flush_workqueue(priv->wq);
        if (test_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &mdev->intf_state)) {
                netif_device_detach(netdev);
-               mutex_lock(&priv->state_lock);
-               if (test_bit(MLX5E_STATE_OPENED, &priv->state))
-                       mlx5e_close_locked(netdev);
-               mutex_unlock(&priv->state_lock);
+               mlx5e_close(netdev);
        } else {
                unregister_netdev(netdev);
        }
index 229ab16..b000ddc 100644 (file)
@@ -317,7 +317,8 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
        while ((sq->pc & wq->sz_m1) > sq->edge)
                mlx5e_send_nop(sq, false);
 
-       sq->bf_budget = bf ? sq->bf_budget - 1 : 0;
+       if (bf)
+               sq->bf_budget--;
 
        sq->stats.packets++;
        sq->stats.bytes += num_bytes;
index b84a691..aebbd6c 100644 (file)
@@ -383,7 +383,7 @@ __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule,
                                   match_v,
                                   MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
                                   0, &dest);
-       if (IS_ERR_OR_NULL(flow_rule)) {
+       if (IS_ERR(flow_rule)) {
                pr_warn(
                        "FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%ld)\n",
                         dmac_v, dmac_c, vport, PTR_ERR(flow_rule));
@@ -457,7 +457,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports)
 
        table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
        fdb = mlx5_create_flow_table(root_ns, 0, table_size, 0);
-       if (IS_ERR_OR_NULL(fdb)) {
+       if (IS_ERR(fdb)) {
                err = PTR_ERR(fdb);
                esw_warn(dev, "Failed to create FDB Table err %d\n", err);
                goto out;
@@ -474,7 +474,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports)
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
        eth_broadcast_addr(dmac);
        g = mlx5_create_flow_group(fdb, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create flow group err(%d)\n", err);
                goto out;
@@ -489,7 +489,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports)
        eth_zero_addr(dmac);
        dmac[0] = 0x01;
        g = mlx5_create_flow_group(fdb, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
                goto out;
@@ -506,7 +506,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports)
        MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
        g = mlx5_create_flow_group(fdb, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
                goto out;
@@ -529,7 +529,7 @@ out:
                }
        }
 
-       kfree(flow_group_in);
+       kvfree(flow_group_in);
        return err;
 }
 
@@ -651,6 +651,7 @@ static void update_allmulti_vports(struct mlx5_eswitch *esw,
                                        esw_fdb_set_vport_rule(esw,
                                                               mac,
                                                               vport_idx);
+                       iter_vaddr->mc_promisc = true;
                        break;
                case MLX5_ACTION_DEL:
                        if (!iter_vaddr)
@@ -1060,7 +1061,7 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
                return;
 
        acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
-       if (IS_ERR_OR_NULL(acl)) {
+       if (IS_ERR(acl)) {
                err = PTR_ERR(acl);
                esw_warn(dev, "Failed to create E-Switch vport[%d] egress flow Table, err(%d)\n",
                         vport->vport, err);
@@ -1075,7 +1076,7 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
 
        vlan_grp = mlx5_create_flow_group(acl, flow_group_in);
-       if (IS_ERR_OR_NULL(vlan_grp)) {
+       if (IS_ERR(vlan_grp)) {
                err = PTR_ERR(vlan_grp);
                esw_warn(dev, "Failed to create E-Switch vport[%d] egress allowed vlans flow group, err(%d)\n",
                         vport->vport, err);
@@ -1086,7 +1087,7 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
        MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
        drop_grp = mlx5_create_flow_group(acl, flow_group_in);
-       if (IS_ERR_OR_NULL(drop_grp)) {
+       if (IS_ERR(drop_grp)) {
                err = PTR_ERR(drop_grp);
                esw_warn(dev, "Failed to create E-Switch vport[%d] egress drop flow group, err(%d)\n",
                         vport->vport, err);
@@ -1097,7 +1098,7 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
        vport->egress.drop_grp = drop_grp;
        vport->egress.allowed_vlans_grp = vlan_grp;
 out:
-       kfree(flow_group_in);
+       kvfree(flow_group_in);
        if (err && !IS_ERR_OR_NULL(vlan_grp))
                mlx5_destroy_flow_group(vlan_grp);
        if (err && !IS_ERR_OR_NULL(acl))
@@ -1174,7 +1175,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
                return;
 
        acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
-       if (IS_ERR_OR_NULL(acl)) {
+       if (IS_ERR(acl)) {
                err = PTR_ERR(acl);
                esw_warn(dev, "Failed to create E-Switch vport[%d] ingress flow Table, err(%d)\n",
                         vport->vport, err);
@@ -1192,7 +1193,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
 
        g = mlx5_create_flow_group(acl, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create E-Switch vport[%d] ingress untagged spoofchk flow group, err(%d)\n",
                         vport->vport, err);
@@ -1207,7 +1208,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
 
        g = mlx5_create_flow_group(acl, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create E-Switch vport[%d] ingress untagged flow group, err(%d)\n",
                         vport->vport, err);
@@ -1223,7 +1224,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 2);
 
        g = mlx5_create_flow_group(acl, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create E-Switch vport[%d] ingress spoofchk flow group, err(%d)\n",
                         vport->vport, err);
@@ -1236,7 +1237,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 3);
 
        g = mlx5_create_flow_group(acl, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create E-Switch vport[%d] ingress drop flow group, err(%d)\n",
                         vport->vport, err);
@@ -1259,7 +1260,7 @@ out:
                        mlx5_destroy_flow_table(vport->ingress.acl);
        }
 
-       kfree(flow_group_in);
+       kvfree(flow_group_in);
 }
 
 static void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw,
@@ -1363,7 +1364,7 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
                                   match_v,
                                   MLX5_FLOW_CONTEXT_ACTION_ALLOW,
                                   0, NULL);
-       if (IS_ERR_OR_NULL(vport->ingress.allow_rule)) {
+       if (IS_ERR(vport->ingress.allow_rule)) {
                err = PTR_ERR(vport->ingress.allow_rule);
                pr_warn("vport[%d] configure ingress allow rule, err(%d)\n",
                        vport->vport, err);
@@ -1380,7 +1381,7 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
                                   match_v,
                                   MLX5_FLOW_CONTEXT_ACTION_DROP,
                                   0, NULL);
-       if (IS_ERR_OR_NULL(vport->ingress.drop_rule)) {
+       if (IS_ERR(vport->ingress.drop_rule)) {
                err = PTR_ERR(vport->ingress.drop_rule);
                pr_warn("vport[%d] configure ingress drop rule, err(%d)\n",
                        vport->vport, err);
@@ -1439,7 +1440,7 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw,
                                   match_v,
                                   MLX5_FLOW_CONTEXT_ACTION_ALLOW,
                                   0, NULL);
-       if (IS_ERR_OR_NULL(vport->egress.allowed_vlan)) {
+       if (IS_ERR(vport->egress.allowed_vlan)) {
                err = PTR_ERR(vport->egress.allowed_vlan);
                pr_warn("vport[%d] configure egress allowed vlan rule failed, err(%d)\n",
                        vport->vport, err);
@@ -1457,7 +1458,7 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw,
                                   match_v,
                                   MLX5_FLOW_CONTEXT_ACTION_DROP,
                                   0, NULL);
-       if (IS_ERR_OR_NULL(vport->egress.drop_rule)) {
+       if (IS_ERR(vport->egress.drop_rule)) {
                err = PTR_ERR(vport->egress.drop_rule);
                pr_warn("vport[%d] configure egress drop rule failed, err(%d)\n",
                        vport->vport, err);
@@ -1491,14 +1492,11 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,
 
        /* Sync with current vport context */
        vport->enabled_events = enable_events;
-       esw_vport_change_handle_locked(vport);
-
        vport->enabled = true;
 
        /* only PF is trusted by default */
        vport->trusted = (vport_num) ? false : true;
-
-       arm_vport_context_events_cmd(esw->dev, vport_num, enable_events);
+       esw_vport_change_handle_locked(vport);
 
        esw->enabled_vports++;
        esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num);
@@ -1728,11 +1726,24 @@ void mlx5_eswitch_vport_event(struct mlx5_eswitch *esw, struct mlx5_eqe *eqe)
        (esw && MLX5_CAP_GEN(esw->dev, vport_group_manager) && mlx5_core_is_pf(esw->dev))
 #define LEGAL_VPORT(esw, vport) (vport >= 0 && vport < esw->total_vports)
 
+static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN])
+{
+       ((u8 *)node_guid)[7] = mac[0];
+       ((u8 *)node_guid)[6] = mac[1];
+       ((u8 *)node_guid)[5] = mac[2];
+       ((u8 *)node_guid)[4] = 0xff;
+       ((u8 *)node_guid)[3] = 0xfe;
+       ((u8 *)node_guid)[2] = mac[3];
+       ((u8 *)node_guid)[1] = mac[4];
+       ((u8 *)node_guid)[0] = mac[5];
+}
+
 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
                               int vport, u8 mac[ETH_ALEN])
 {
-       int err = 0;
        struct mlx5_vport *evport;
+       u64 node_guid;
+       int err = 0;
 
        if (!ESW_ALLOWED(esw))
                return -EPERM;
@@ -1756,11 +1767,17 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
                return err;
        }
 
+       node_guid_gen_from_mac(&node_guid, mac);
+       err = mlx5_modify_nic_vport_node_guid(esw->dev, vport, node_guid);
+       if (err)
+               mlx5_core_warn(esw->dev,
+                              "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n",
+                              vport, err);
+
        mutex_lock(&esw->state_lock);
        if (evport->enabled)
                err = esw_vport_ingress_config(esw, evport);
        mutex_unlock(&esw->state_lock);
-
        return err;
 }
 
index 8b5f0b2..e912a3d 100644 (file)
@@ -1292,8 +1292,8 @@ static int update_root_ft_destroy(struct mlx5_flow_table *ft)
                                       ft->id);
                        return err;
                }
-               root->root_ft = new_root_ft;
        }
+       root->root_ft = new_root_ft;
        return 0;
 }
 
@@ -1767,6 +1767,9 @@ static void cleanup_root_ns(struct mlx5_core_dev *dev)
 
 void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
 {
+       if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
+               return;
+
        cleanup_root_ns(dev);
        cleanup_single_prio_root_ns(dev, dev->priv.fdb_root_ns);
        cleanup_single_prio_root_ns(dev, dev->priv.esw_egress_root_ns);
@@ -1828,29 +1831,36 @@ int mlx5_init_fs(struct mlx5_core_dev *dev)
 {
        int err = 0;
 
+       if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
+               return 0;
+
        err = mlx5_init_fc_stats(dev);
        if (err)
                return err;
 
-       if (MLX5_CAP_GEN(dev, nic_flow_table)) {
+       if (MLX5_CAP_GEN(dev, nic_flow_table) &&
+           MLX5_CAP_FLOWTABLE_NIC_RX(dev, ft_support)) {
                err = init_root_ns(dev);
                if (err)
                        goto err;
        }
+
        if (MLX5_CAP_GEN(dev, eswitch_flow_table)) {
-               err = init_fdb_root_ns(dev);
-               if (err)
-                       goto err;
-       }
-       if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
-               err = init_egress_acl_root_ns(dev);
-               if (err)
-                       goto err;
-       }
-       if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
-               err = init_ingress_acl_root_ns(dev);
-               if (err)
-                       goto err;
+               if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, ft_support)) {
+                       err = init_fdb_root_ns(dev);
+                       if (err)
+                               goto err;
+               }
+               if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
+                       err = init_egress_acl_root_ns(dev);
+                       if (err)
+                               goto err;
+               }
+               if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
+                       err = init_ingress_acl_root_ns(dev);
+                       if (err)
+                               goto err;
+               }
        }
 
        return 0;
index b720a27..b82d658 100644 (file)
@@ -418,7 +418,7 @@ int mlx5_core_xrcd_alloc(struct mlx5_core_dev *dev, u32 *xrcdn)
        if (out.hdr.status)
                err = mlx5_cmd_status_to_err(&out.hdr);
        else
-               *xrcdn = be32_to_cpu(out.xrcdn);
+               *xrcdn = be32_to_cpu(out.xrcdn) & 0xffffff;
 
        return err;
 }
index b69dadc..daf44cd 100644 (file)
@@ -508,6 +508,44 @@ int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid)
 }
 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid);
 
+int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev,
+                                   u32 vport, u64 node_guid)
+{
+       int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
+       void *nic_vport_context;
+       u8 *guid;
+       void *in;
+       int err;
+
+       if (!vport)
+               return -EINVAL;
+       if (!MLX5_CAP_GEN(mdev, vport_group_manager))
+               return -EACCES;
+       if (!MLX5_CAP_ESW(mdev, nic_vport_node_guid_modify))
+               return -ENOTSUPP;
+
+       in = mlx5_vzalloc(inlen);
+       if (!in)
+               return -ENOMEM;
+
+       MLX5_SET(modify_nic_vport_context_in, in,
+                field_select.node_guid, 1);
+       MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
+       MLX5_SET(modify_nic_vport_context_in, in, other_vport, !!vport);
+
+       nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in,
+                                        in, nic_vport_context);
+       guid = MLX5_ADDR_OF(nic_vport_context, nic_vport_context,
+                           node_guid);
+       MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid);
+
+       err = mlx5_modify_nic_vport_context(mdev, in, inlen);
+
+       kvfree(in);
+
+       return err;
+}
+
 int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev,
                                        u16 *qkey_viol_cntr)
 {
index 4a72737..6f9e3dd 100644 (file)
@@ -247,15 +247,23 @@ static int mlxsw_sp_port_mtu_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu)
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl);
 }
 
-static int mlxsw_sp_port_swid_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 swid)
+static int __mlxsw_sp_port_swid_set(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+                                   u8 swid)
 {
-       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        char pspa_pl[MLXSW_REG_PSPA_LEN];
 
-       mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sp_port->local_port);
+       mlxsw_reg_pspa_pack(pspa_pl, swid, local_port);
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pspa), pspa_pl);
 }
 
+static int mlxsw_sp_port_swid_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 swid)
+{
+       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+
+       return __mlxsw_sp_port_swid_set(mlxsw_sp, mlxsw_sp_port->local_port,
+                                       swid);
+}
+
 static int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port,
                                     bool enable)
 {
@@ -305,9 +313,9 @@ mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port)
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sspr), sspr_pl);
 }
 
-static int __mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp,
-                                          u8 local_port, u8 *p_module,
-                                          u8 *p_width, u8 *p_lane)
+static int mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp,
+                                        u8 local_port, u8 *p_module,
+                                        u8 *p_width, u8 *p_lane)
 {
        char pmlp_pl[MLXSW_REG_PMLP_LEN];
        int err;
@@ -322,16 +330,6 @@ static int __mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp,
        return 0;
 }
 
-static int mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp,
-                                        u8 local_port, u8 *p_module,
-                                        u8 *p_width)
-{
-       u8 lane;
-
-       return __mlxsw_sp_port_module_info_get(mlxsw_sp, local_port, p_module,
-                                              p_width, &lane);
-}
-
 static int mlxsw_sp_port_module_map(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                                    u8 module, u8 width, u8 lane)
 {
@@ -949,17 +947,11 @@ static int mlxsw_sp_port_get_phys_port_name(struct net_device *dev, char *name,
                                            size_t len)
 {
        struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
-       u8 module, width, lane;
+       u8 module = mlxsw_sp_port->mapping.module;
+       u8 width = mlxsw_sp_port->mapping.width;
+       u8 lane = mlxsw_sp_port->mapping.lane;
        int err;
 
-       err = __mlxsw_sp_port_module_info_get(mlxsw_sp_port->mlxsw_sp,
-                                             mlxsw_sp_port->local_port,
-                                             &module, &width, &lane);
-       if (err) {
-               netdev_err(dev, "Failed to retrieve module information\n");
-               return err;
-       }
-
        if (!mlxsw_sp_port->split)
                err = snprintf(name, len, "p%d", module + 1);
        else
@@ -1681,8 +1673,8 @@ static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port)
        return 0;
 }
 
-static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
-                                 bool split, u8 module, u8 width)
+static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+                               bool split, u8 module, u8 width, u8 lane)
 {
        struct mlxsw_sp_port *mlxsw_sp_port;
        struct net_device *dev;
@@ -1697,6 +1689,9 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
        mlxsw_sp_port->mlxsw_sp = mlxsw_sp;
        mlxsw_sp_port->local_port = local_port;
        mlxsw_sp_port->split = split;
+       mlxsw_sp_port->mapping.module = module;
+       mlxsw_sp_port->mapping.width = width;
+       mlxsw_sp_port->mapping.lane = lane;
        bytes = DIV_ROUND_UP(VLAN_N_VID, BITS_PER_BYTE);
        mlxsw_sp_port->active_vlans = kzalloc(bytes, GFP_KERNEL);
        if (!mlxsw_sp_port->active_vlans) {
@@ -1839,28 +1834,6 @@ err_port_active_vlans_alloc:
        return err;
 }
 
-static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
-                               bool split, u8 module, u8 width, u8 lane)
-{
-       int err;
-
-       err = mlxsw_sp_port_module_map(mlxsw_sp, local_port, module, width,
-                                      lane);
-       if (err)
-               return err;
-
-       err = __mlxsw_sp_port_create(mlxsw_sp, local_port, split, module,
-                                    width);
-       if (err)
-               goto err_port_create;
-
-       return 0;
-
-err_port_create:
-       mlxsw_sp_port_module_unmap(mlxsw_sp, local_port);
-       return err;
-}
-
 static void mlxsw_sp_port_vports_fini(struct mlxsw_sp_port *mlxsw_sp_port)
 {
        struct net_device *dev = mlxsw_sp_port->dev;
@@ -1909,8 +1882,8 @@ static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp)
 
 static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
 {
+       u8 module, width, lane;
        size_t alloc_size;
-       u8 module, width;
        int i;
        int err;
 
@@ -1921,13 +1894,14 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
 
        for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) {
                err = mlxsw_sp_port_module_info_get(mlxsw_sp, i, &module,
-                                                   &width);
+                                                   &width, &lane);
                if (err)
                        goto err_port_module_info_get;
                if (!width)
                        continue;
                mlxsw_sp->port_to_module[i] = module;
-               err = __mlxsw_sp_port_create(mlxsw_sp, i, false, module, width);
+               err = mlxsw_sp_port_create(mlxsw_sp, i, false, module, width,
+                                          lane);
                if (err)
                        goto err_port_create;
        }
@@ -1948,12 +1922,85 @@ static u8 mlxsw_sp_cluster_base_port_get(u8 local_port)
        return local_port - offset;
 }
 
+static int mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port,
+                                     u8 module, unsigned int count)
+{
+       u8 width = MLXSW_PORT_MODULE_MAX_WIDTH / count;
+       int err, i;
+
+       for (i = 0; i < count; i++) {
+               err = mlxsw_sp_port_module_map(mlxsw_sp, base_port + i, module,
+                                              width, i * width);
+               if (err)
+                       goto err_port_module_map;
+       }
+
+       for (i = 0; i < count; i++) {
+               err = __mlxsw_sp_port_swid_set(mlxsw_sp, base_port + i, 0);
+               if (err)
+                       goto err_port_swid_set;
+       }
+
+       for (i = 0; i < count; i++) {
+               err = mlxsw_sp_port_create(mlxsw_sp, base_port + i, true,
+                                          module, width, i * width);
+               if (err)
+                       goto err_port_create;
+       }
+
+       return 0;
+
+err_port_create:
+       for (i--; i >= 0; i--)
+               mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
+       i = count;
+err_port_swid_set:
+       for (i--; i >= 0; i--)
+               __mlxsw_sp_port_swid_set(mlxsw_sp, base_port + i,
+                                        MLXSW_PORT_SWID_DISABLED_PORT);
+       i = count;
+err_port_module_map:
+       for (i--; i >= 0; i--)
+               mlxsw_sp_port_module_unmap(mlxsw_sp, base_port + i);
+       return err;
+}
+
+static void mlxsw_sp_port_unsplit_create(struct mlxsw_sp *mlxsw_sp,
+                                        u8 base_port, unsigned int count)
+{
+       u8 local_port, module, width = MLXSW_PORT_MODULE_MAX_WIDTH;
+       int i;
+
+       /* Split by four means we need to re-create two ports, otherwise
+        * only one.
+        */
+       count = count / 2;
+
+       for (i = 0; i < count; i++) {
+               local_port = base_port + i * 2;
+               module = mlxsw_sp->port_to_module[local_port];
+
+               mlxsw_sp_port_module_map(mlxsw_sp, local_port, module, width,
+                                        0);
+       }
+
+       for (i = 0; i < count; i++)
+               __mlxsw_sp_port_swid_set(mlxsw_sp, base_port + i * 2, 0);
+
+       for (i = 0; i < count; i++) {
+               local_port = base_port + i * 2;
+               module = mlxsw_sp->port_to_module[local_port];
+
+               mlxsw_sp_port_create(mlxsw_sp, local_port, false, module,
+                                    width, 0);
+       }
+}
+
 static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
                               unsigned int count)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
        struct mlxsw_sp_port *mlxsw_sp_port;
-       u8 width = MLXSW_PORT_MODULE_MAX_WIDTH / count;
        u8 module, cur_width, base_port;
        int i;
        int err;
@@ -1965,18 +2012,14 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
                return -EINVAL;
        }
 
+       module = mlxsw_sp_port->mapping.module;
+       cur_width = mlxsw_sp_port->mapping.width;
+
        if (count != 2 && count != 4) {
                netdev_err(mlxsw_sp_port->dev, "Port can only be split into 2 or 4 ports\n");
                return -EINVAL;
        }
 
-       err = mlxsw_sp_port_module_info_get(mlxsw_sp, local_port, &module,
-                                           &cur_width);
-       if (err) {
-               netdev_err(mlxsw_sp_port->dev, "Failed to get port's width\n");
-               return err;
-       }
-
        if (cur_width != MLXSW_PORT_MODULE_MAX_WIDTH) {
                netdev_err(mlxsw_sp_port->dev, "Port cannot be split further\n");
                return -EINVAL;
@@ -2001,25 +2044,16 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
        for (i = 0; i < count; i++)
                mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
 
-       for (i = 0; i < count; i++) {
-               err = mlxsw_sp_port_create(mlxsw_sp, base_port + i, true,
-                                          module, width, i * width);
-               if (err) {
-                       dev_err(mlxsw_sp->bus_info->dev, "Failed to create split port\n");
-                       goto err_port_create;
-               }
+       err = mlxsw_sp_port_split_create(mlxsw_sp, base_port, module, count);
+       if (err) {
+               dev_err(mlxsw_sp->bus_info->dev, "Failed to create split ports\n");
+               goto err_port_split_create;
        }
 
        return 0;
 
-err_port_create:
-       for (i--; i >= 0; i--)
-               mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
-       for (i = 0; i < count / 2; i++) {
-               module = mlxsw_sp->port_to_module[base_port + i * 2];
-               mlxsw_sp_port_create(mlxsw_sp, base_port + i * 2, false,
-                                    module, MLXSW_PORT_MODULE_MAX_WIDTH, 0);
-       }
+err_port_split_create:
+       mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count);
        return err;
 }
 
@@ -2027,10 +2061,9 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
        struct mlxsw_sp_port *mlxsw_sp_port;
-       u8 module, cur_width, base_port;
+       u8 cur_width, base_port;
        unsigned int count;
        int i;
-       int err;
 
        mlxsw_sp_port = mlxsw_sp->ports[local_port];
        if (!mlxsw_sp_port) {
@@ -2044,12 +2077,7 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port)
                return -EINVAL;
        }
 
-       err = mlxsw_sp_port_module_info_get(mlxsw_sp, local_port, &module,
-                                           &cur_width);
-       if (err) {
-               netdev_err(mlxsw_sp_port->dev, "Failed to get port's width\n");
-               return err;
-       }
+       cur_width = mlxsw_sp_port->mapping.width;
        count = cur_width == 1 ? 4 : 2;
 
        base_port = mlxsw_sp_cluster_base_port_get(local_port);
@@ -2061,14 +2089,7 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port)
        for (i = 0; i < count; i++)
                mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
 
-       for (i = 0; i < count / 2; i++) {
-               module = mlxsw_sp->port_to_module[base_port + i * 2];
-               err = mlxsw_sp_port_create(mlxsw_sp, base_port + i * 2, false,
-                                          module, MLXSW_PORT_MODULE_MAX_WIDTH,
-                                          0);
-               if (err)
-                       dev_err(mlxsw_sp->bus_info->dev, "Failed to reinstantiate port\n");
-       }
+       mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count);
 
        return 0;
 }
index e2c022d..13b30ea 100644 (file)
@@ -229,6 +229,11 @@ struct mlxsw_sp_port {
                struct ieee_maxrate *maxrate;
                struct ieee_pfc *pfc;
        } dcb;
+       struct {
+               u8 module;
+               u8 width;
+               u8 lane;
+       } mapping;
        /* 802.1Q bridge VLANs */
        unsigned long *active_vlans;
        unsigned long *untagged_vlans;
index 7530646..61cc686 100644 (file)
@@ -1105,6 +1105,39 @@ static int qed_get_port_type(u32 media_type)
        return port_type;
 }
 
+static int qed_get_link_data(struct qed_hwfn *hwfn,
+                            struct qed_mcp_link_params *params,
+                            struct qed_mcp_link_state *link,
+                            struct qed_mcp_link_capabilities *link_caps)
+{
+       void *p;
+
+       if (!IS_PF(hwfn->cdev)) {
+               qed_vf_get_link_params(hwfn, params);
+               qed_vf_get_link_state(hwfn, link);
+               qed_vf_get_link_caps(hwfn, link_caps);
+
+               return 0;
+       }
+
+       p = qed_mcp_get_link_params(hwfn);
+       if (!p)
+               return -ENXIO;
+       memcpy(params, p, sizeof(*params));
+
+       p = qed_mcp_get_link_state(hwfn);
+       if (!p)
+               return -ENXIO;
+       memcpy(link, p, sizeof(*link));
+
+       p = qed_mcp_get_link_capabilities(hwfn);
+       if (!p)
+               return -ENXIO;
+       memcpy(link_caps, p, sizeof(*link_caps));
+
+       return 0;
+}
+
 static void qed_fill_link(struct qed_hwfn *hwfn,
                          struct qed_link_output *if_link)
 {
@@ -1116,15 +1149,9 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
        memset(if_link, 0, sizeof(*if_link));
 
        /* Prepare source inputs */
-       if (IS_PF(hwfn->cdev)) {
-               memcpy(&params, qed_mcp_get_link_params(hwfn), sizeof(params));
-               memcpy(&link, qed_mcp_get_link_state(hwfn), sizeof(link));
-               memcpy(&link_caps, qed_mcp_get_link_capabilities(hwfn),
-                      sizeof(link_caps));
-       } else {
-               qed_vf_get_link_params(hwfn, &params);
-               qed_vf_get_link_state(hwfn, &link);
-               qed_vf_get_link_caps(hwfn, &link_caps);
+       if (qed_get_link_data(hwfn, &params, &link, &link_caps)) {
+               dev_warn(&hwfn->cdev->pdev->dev, "no link data available\n");
+               return;
        }
 
        /* Set the link parameters to pass to protocol driver */
index c8667c6..c90b2b6 100644 (file)
 #include "qed_vf.h"
 #define QED_VF_ARRAY_LENGTH (3)
 
+#ifdef CONFIG_QED_SRIOV
 #define IS_VF(cdev)             ((cdev)->b_is_vf)
 #define IS_PF(cdev)             (!((cdev)->b_is_vf))
-#ifdef CONFIG_QED_SRIOV
 #define IS_PF_SRIOV(p_hwfn)     (!!((p_hwfn)->cdev->p_iov_info))
 #else
+#define IS_VF(cdev)             (0)
+#define IS_PF(cdev)             (1)
 #define IS_PF_SRIOV(p_hwfn)     (0)
 #endif
 #define IS_PF_SRIOV_ALLOC(p_hwfn)       (!!((p_hwfn)->pf_iov_info))
index 5d00d14..5733d18 100644 (file)
@@ -87,7 +87,9 @@ static const struct pci_device_id qede_pci_tbl[] = {
        {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_100), QEDE_PRIVATE_PF},
        {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_50), QEDE_PRIVATE_PF},
        {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_25), QEDE_PRIVATE_PF},
+#ifdef CONFIG_QED_SRIOV
        {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_IOV), QEDE_PRIVATE_VF},
+#endif
        { 0 }
 };
 
index 7f295c4..2a9228a 100644 (file)
@@ -189,11 +189,12 @@ static u32 mcdi_to_ethtool_cap(u32 media, u32 cap)
 
        case MC_CMD_MEDIA_XFP:
        case MC_CMD_MEDIA_SFP_PLUS:
-               result |= SUPPORTED_FIBRE;
-               break;
-
        case MC_CMD_MEDIA_QSFP_PLUS:
                result |= SUPPORTED_FIBRE;
+               if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
+                       result |= SUPPORTED_1000baseT_Full;
+               if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
+                       result |= SUPPORTED_10000baseT_Full;
                if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
                        result |= SUPPORTED_40000baseCR4_Full;
                break;
index 4f7283d..44da877 100644 (file)
@@ -156,7 +156,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
                struct netdev_hw_addr *ha;
 
                netdev_for_each_uc_addr(ha, dev) {
-                       dwmac4_set_umac_addr(ioaddr, ha->addr, reg);
+                       dwmac4_set_umac_addr(hw, ha->addr, reg);
                        reg++;
                }
        }
index eac45d0..a473c18 100644 (file)
@@ -3450,8 +3450,6 @@ int stmmac_resume(struct device *dev)
        if (!netif_running(ndev))
                return 0;
 
-       spin_lock_irqsave(&priv->lock, flags);
-
        /* Power Down bit, into the PM register, is cleared
         * automatically as soon as a magic packet or a Wake-up frame
         * is received. Anyway, it's better to manually clear
@@ -3459,7 +3457,9 @@ int stmmac_resume(struct device *dev)
         * from another devices (e.g. serial console).
         */
        if (device_may_wakeup(priv->device)) {
+               spin_lock_irqsave(&priv->lock, flags);
                priv->hw->mac->pmt(priv->hw, 0);
+               spin_unlock_irqrestore(&priv->lock, flags);
                priv->irq_wake = 0;
        } else {
                pinctrl_pm_select_default_state(priv->device);
@@ -3473,6 +3473,8 @@ int stmmac_resume(struct device *dev)
 
        netif_device_attach(ndev);
 
+       spin_lock_irqsave(&priv->lock, flags);
+
        priv->cur_rx = 0;
        priv->dirty_rx = 0;
        priv->dirty_tx = 0;
index 4b08a2f..e6bb0ec 100644 (file)
@@ -1339,7 +1339,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
        if (priv->coal_intvl != 0) {
                struct ethtool_coalesce coal;
 
-               coal.rx_coalesce_usecs = (priv->coal_intvl << 4);
+               coal.rx_coalesce_usecs = priv->coal_intvl;
                cpsw_set_coalesce(ndev, &coal);
        }
 
index db8022a..08885bc 100644 (file)
@@ -1369,7 +1369,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
                                rcdlro = (struct Vmxnet3_RxCompDescExt *)rcd;
 
                                segCnt = rcdlro->segCnt;
-                               BUG_ON(segCnt <= 1);
+                               WARN_ON_ONCE(segCnt == 0);
                                mss = rcdlro->mss;
                                if (unlikely(segCnt <= 1))
                                        segCnt = 0;
index c482539..3d2b64e 100644 (file)
 /*
  * Version numbers
  */
-#define VMXNET3_DRIVER_VERSION_STRING   "1.4.7.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING   "1.4.8.0-k"
 
 /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01040700
+#define VMXNET3_DRIVER_VERSION_NUM      0x01040800
 
 #if defined(CONFIG_PCI_MSI)
        /* RSS only makes sense if MSI-X is supported. */
index d0631b6..62f475e 100644 (file)
@@ -2540,12 +2540,14 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
                           const u8 *mac, struct station_info *sinfo)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_scb_val_le scb_val;
        s32 err = 0;
        struct brcmf_sta_info_le sta_info_le;
        u32 sta_flags;
        u32 is_tdls_peer;
        s32 total_rssi;
        s32 count_rssi;
+       int rssi;
        u32 i;
 
        brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
@@ -2629,6 +2631,20 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
                        sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
                        total_rssi /= count_rssi;
                        sinfo->signal = total_rssi;
+               } else if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
+                       &ifp->vif->sme_state)) {
+                       memset(&scb_val, 0, sizeof(scb_val));
+                       err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
+                                                    &scb_val, sizeof(scb_val));
+                       if (err) {
+                               brcmf_err("Could not get rssi (%d)\n", err);
+                               goto done;
+                       } else {
+                               rssi = le32_to_cpu(scb_val.val);
+                               sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
+                               sinfo->signal = rssi;
+                               brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
+                       }
                }
        }
 done:
index 68f1ce0..2b9a2bc 100644 (file)
@@ -1157,6 +1157,8 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
                brcmu_pkt_buf_free_skb(skb);
                return;
        }
+
+       skb->protocol = eth_type_trans(skb, ifp->ndev);
        brcmf_netif_rx(ifp, skb);
 }
 
index 9ed0ed1..4dd5adc 100644 (file)
@@ -2776,6 +2776,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
        if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
            !info->attrs[HWSIM_ATTR_FLAGS] ||
            !info->attrs[HWSIM_ATTR_COOKIE] ||
+           !info->attrs[HWSIM_ATTR_SIGNAL] ||
            !info->attrs[HWSIM_ATTR_TX_INFO])
                goto out;
 
index 0f48048..3a0faa8 100644 (file)
@@ -54,7 +54,7 @@ EXPORT_SYMBOL(channel5g_80m);
 void rtl_addr_delay(u32 addr)
 {
        if (addr == 0xfe)
-               msleep(50);
+               mdelay(50);
        else if (addr == 0xfd)
                msleep(5);
        else if (addr == 0xfc)
@@ -75,7 +75,7 @@ void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr,
                rtl_addr_delay(addr);
        } else {
                rtl_set_rfreg(hw, rfpath, addr, mask, data);
-               usleep_range(1, 2);
+               udelay(1);
        }
 }
 EXPORT_SYMBOL(rtl_rfreg_delay);
@@ -86,7 +86,7 @@ void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data)
                rtl_addr_delay(addr);
        } else {
                rtl_set_bbreg(hw, addr, MASKDWORD, data);
-               usleep_range(1, 2);
+               udelay(1);
        }
 }
 EXPORT_SYMBOL(rtl_bb_delay);
index 786ad32..07b83d3 100644 (file)
@@ -152,6 +152,8 @@ extern void cpuidle_disable_device(struct cpuidle_device *dev);
 extern int cpuidle_play_dead(void);
 
 extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev);
+static inline struct cpuidle_device *cpuidle_get_device(void)
+{return __this_cpu_read(cpuidle_devices); }
 #else
 static inline void disable_cpuidle(void) { }
 static inline bool cpuidle_not_available(struct cpuidle_driver *drv,
@@ -187,6 +189,7 @@ static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
 static inline int cpuidle_play_dead(void) {return -ENODEV; }
 static inline struct cpuidle_driver *cpuidle_get_cpu_driver(
        struct cpuidle_device *dev) {return NULL; }
+static inline struct cpuidle_device *cpuidle_get_device(void) {return NULL; }
 #endif
 
 #if defined(CONFIG_CPU_IDLE) && defined(CONFIG_SUSPEND)
index 035abdf..73a4847 100644 (file)
@@ -1240,8 +1240,6 @@ struct mlx5_destroy_psv_out {
        u8                      rsvd[8];
 };
 
-#define MLX5_CMD_OP_MAX 0x920
-
 enum {
        VPORT_STATE_DOWN                = 0x0,
        VPORT_STATE_UP                  = 0x1,
@@ -1369,6 +1367,12 @@ enum mlx5_cap_type {
 #define MLX5_CAP_FLOWTABLE_MAX(mdev, cap) \
        MLX5_GET(flow_table_nic_cap, mdev->hca_caps_max[MLX5_CAP_FLOW_TABLE], cap)
 
+#define MLX5_CAP_FLOWTABLE_NIC_RX(mdev, cap) \
+       MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_receive.cap)
+
+#define MLX5_CAP_FLOWTABLE_NIC_RX_MAX(mdev, cap) \
+       MLX5_CAP_FLOWTABLE_MAX(mdev, flow_table_properties_nic_receive.cap)
+
 #define MLX5_CAP_ESW_FLOWTABLE(mdev, cap) \
        MLX5_GET(flow_table_eswitch_cap, \
                 mdev->hca_caps_cur[MLX5_CAP_ESWITCH_FLOW_TABLE], cap)
index 9a05cd7..e955a28 100644 (file)
@@ -205,7 +205,8 @@ enum {
        MLX5_CMD_OP_ALLOC_FLOW_COUNTER            = 0x939,
        MLX5_CMD_OP_DEALLOC_FLOW_COUNTER          = 0x93a,
        MLX5_CMD_OP_QUERY_FLOW_COUNTER            = 0x93b,
-       MLX5_CMD_OP_MODIFY_FLOW_TABLE             = 0x93c
+       MLX5_CMD_OP_MODIFY_FLOW_TABLE             = 0x93c,
+       MLX5_CMD_OP_MAX
 };
 
 struct mlx5_ifc_flow_table_fields_supported_bits {
@@ -500,7 +501,9 @@ struct mlx5_ifc_e_switch_cap_bits {
        u8         vport_svlan_insert[0x1];
        u8         vport_cvlan_insert_if_not_exist[0x1];
        u8         vport_cvlan_insert_overwrite[0x1];
-       u8         reserved_at_5[0x1b];
+       u8         reserved_at_5[0x19];
+       u8         nic_vport_node_guid_modify[0x1];
+       u8         nic_vport_port_guid_modify[0x1];
 
        u8         reserved_at_20[0x7e0];
 };
@@ -4583,7 +4586,10 @@ struct mlx5_ifc_modify_nic_vport_context_out_bits {
 };
 
 struct mlx5_ifc_modify_nic_vport_field_select_bits {
-       u8         reserved_at_0[0x19];
+       u8         reserved_at_0[0x16];
+       u8         node_guid[0x1];
+       u8         port_guid[0x1];
+       u8         reserved_at_18[0x1];
        u8         mtu[0x1];
        u8         change_event[0x1];
        u8         promisc[0x1];
index 6422102..266320f 100644 (file)
@@ -460,10 +460,9 @@ struct mlx5_core_qp {
 };
 
 struct mlx5_qp_path {
-       u8                      fl;
+       u8                      fl_free_ar;
        u8                      rsvd3;
-       u8                      free_ar;
-       u8                      pkey_index;
+       __be16                  pkey_index;
        u8                      rsvd0;
        u8                      grh_mlid;
        __be16                  rlid;
@@ -560,6 +559,7 @@ struct mlx5_modify_qp_mbox_in {
        __be32                  optparam;
        u8                      rsvd0[4];
        struct mlx5_qp_context  ctx;
+       u8                      rsvd2[16];
 };
 
 struct mlx5_modify_qp_mbox_out {
index 301da4a..6c16c19 100644 (file)
@@ -50,6 +50,8 @@ int mlx5_modify_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 mtu);
 int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev,
                                           u64 *system_image_guid);
 int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid);
+int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev,
+                                   u32 vport, u64 node_guid);
 int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev,
                                        u16 *qkey_viol_cntr);
 int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport,
index 48103cf..13de0cc 100644 (file)
@@ -42,6 +42,7 @@ int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
 
 int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *,
                      struct sockaddr __user **, struct iovec **);
+struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval);
 asmlinkage long compat_sys_sendmsg(int, struct compat_msghdr __user *,
                                   unsigned int);
 asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *,
index af4c10e..cd6018a 100644 (file)
@@ -1232,7 +1232,7 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
 const char *ip_vs_state_name(__u16 proto, int state);
 
 void ip_vs_tcp_conn_listen(struct ip_vs_conn *cp);
-int ip_vs_check_template(struct ip_vs_conn *ct);
+int ip_vs_check_template(struct ip_vs_conn *ct, struct ip_vs_dest *cdest);
 void ip_vs_random_dropentry(struct netns_ipvs *ipvs);
 int ip_vs_conn_init(void);
 void ip_vs_conn_cleanup(void);
index 9c5638a..0dbce55 100644 (file)
@@ -28,8 +28,8 @@ struct nf_queue_handler {
                                                struct nf_hook_ops *ops);
 };
 
-void nf_register_queue_handler(const struct nf_queue_handler *qh);
-void nf_unregister_queue_handler(void);
+void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh);
+void nf_unregister_queue_handler(struct net *net);
 void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
 
 void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
index 38aa498..36d7235 100644 (file)
@@ -5,11 +5,13 @@
 
 struct proc_dir_entry;
 struct nf_logger;
+struct nf_queue_handler;
 
 struct netns_nf {
 #if defined CONFIG_PROC_FS
        struct proc_dir_entry *proc_netfilter;
 #endif
+       const struct nf_queue_handler __rcu *queue_handler;
        const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO];
 #ifdef CONFIG_SYSCTL
        struct ctl_table_header *nf_log_dir_header;
index 0f7efa8..3722dda 100644 (file)
@@ -392,16 +392,20 @@ struct tc_cls_u32_offload {
        };
 };
 
-static inline bool tc_should_offload(struct net_device *dev, u32 flags)
+static inline bool tc_should_offload(const struct net_device *dev,
+                                    const struct tcf_proto *tp, u32 flags)
 {
+       const struct Qdisc *sch = tp->q;
+       const struct Qdisc_class_ops *cops = sch->ops->cl_ops;
+
        if (!(dev->features & NETIF_F_HW_TC))
                return false;
-
        if (flags & TCA_CLS_FLAGS_SKIP_HW)
                return false;
-
        if (!dev->netdev_ops->ndo_setup_tc)
                return false;
+       if (cops && cops->tcf_cl_offload)
+               return cops->tcf_cl_offload(tp->classid);
 
        return true;
 }
index a1fd76c..62d5531 100644 (file)
@@ -168,6 +168,7 @@ struct Qdisc_class_ops {
 
        /* Filter manipulation */
        struct tcf_proto __rcu ** (*tcf_chain)(struct Qdisc *, unsigned long);
+       bool                    (*tcf_cl_offload)(u32 classid);
        unsigned long           (*bind_tcf)(struct Qdisc *, unsigned long,
                                        u32 classid);
        void                    (*unbind_tcf)(struct Qdisc *, unsigned long);
@@ -691,9 +692,11 @@ static inline struct sk_buff *qdisc_peek_dequeued(struct Qdisc *sch)
        /* we can reuse ->gso_skb because peek isn't called for root qdiscs */
        if (!sch->gso_skb) {
                sch->gso_skb = sch->dequeue(sch);
-               if (sch->gso_skb)
+               if (sch->gso_skb) {
                        /* it's still part of the queue */
+                       qdisc_qstats_backlog_inc(sch, sch->gso_skb);
                        sch->q.qlen++;
+               }
        }
 
        return sch->gso_skb;
@@ -706,6 +709,7 @@ static inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch)
 
        if (skb) {
                sch->gso_skb = NULL;
+               qdisc_qstats_backlog_dec(sch, skb);
                sch->q.qlen--;
        } else {
                skb = sch->dequeue(sch);
index 432bed5..7e440d4 100644 (file)
@@ -217,10 +217,10 @@ enum ib_device_cap_flags {
        IB_DEVICE_CROSS_CHANNEL         = (1 << 27),
        IB_DEVICE_MANAGED_FLOW_STEERING         = (1 << 29),
        IB_DEVICE_SIGNATURE_HANDOVER            = (1 << 30),
-       IB_DEVICE_ON_DEMAND_PAGING              = (1 << 31),
+       IB_DEVICE_ON_DEMAND_PAGING              = (1ULL << 31),
        IB_DEVICE_SG_GAPS_REG                   = (1ULL << 32),
-       IB_DEVICE_VIRTUAL_FUNCTION              = ((u64)1 << 33),
-       IB_DEVICE_RAW_SCATTER_FCS               = ((u64)1 << 34),
+       IB_DEVICE_VIRTUAL_FUNCTION              = (1ULL << 33),
+       IB_DEVICE_RAW_SCATTER_FCS               = (1ULL << 34),
 };
 
 enum ib_signature_prot_cap {
index ca1054d..72a04a0 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef _UAPI_LINUX_GTP_H_
-#define _UAPI_LINUX_GTP_H__
+#define _UAPI_LINUX_GTP_H_
 
 enum gtp_genl_cmds {
        GTP_CMD_NEWPDP,
index a7f2770..691984c 100644 (file)
@@ -1,5 +1,6 @@
 # UAPI Header export list
 header-y += asequencer.h
+header-y += asoc.h
 header-y += asound.h
 header-y += asound_fm.h
 header-y += compress_offload.h
@@ -10,3 +11,5 @@ header-y += hdsp.h
 header-y += hdspm.h
 header-y += sb16_csp.h
 header-y += sfnt_info.h
+header-y += tlv.h
+header-y += usb_stream.h
index 074994b..04d7cf3 100644 (file)
@@ -614,6 +614,7 @@ free_bufs:
 
        kref_put(&chan->kref, relay_destroy_channel);
        mutex_unlock(&relay_channels_mutex);
+       kfree(chan);
        return NULL;
 }
 EXPORT_SYMBOL_GPL(relay_open);
index bd12c6c..c5aeedf 100644 (file)
@@ -127,7 +127,7 @@ static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev,
  */
 static void cpuidle_idle_call(void)
 {
-       struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
+       struct cpuidle_device *dev = cpuidle_get_device();
        struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
        int next_state, entered_state;
 
index 780bcbe..720b7bb 100644 (file)
@@ -198,7 +198,7 @@ static u64 bpf_perf_event_read(u64 r1, u64 index, u64 r3, u64 r4, u64 r5)
        if (unlikely(index >= array->map.max_entries))
                return -E2BIG;
 
-       file = (struct file *)array->ptrs[index];
+       file = READ_ONCE(array->ptrs[index]);
        if (unlikely(!file))
                return -ENOENT;
 
@@ -247,7 +247,7 @@ static u64 bpf_perf_event_output(u64 r1, u64 r2, u64 flags, u64 r4, u64 size)
        if (unlikely(index >= array->map.max_entries))
                return -E2BIG;
 
-       file = (struct file *)array->ptrs[index];
+       file = READ_ONCE(array->ptrs[index]);
        if (unlikely(!file))
                return -ENOENT;
 
index b8024fa..6c707bf 100644 (file)
@@ -126,6 +126,17 @@ SYSCALL_DEFINE4(fadvise64_64, int, fd, loff_t, offset, loff_t, len, int, advice)
                 */
                start_index = (offset+(PAGE_SIZE-1)) >> PAGE_SHIFT;
                end_index = (endbyte >> PAGE_SHIFT);
+               if ((endbyte & ~PAGE_MASK) != ~PAGE_MASK) {
+                       /* First page is tricky as 0 - 1 = -1, but pgoff_t
+                        * is unsigned, so the end_index >= start_index
+                        * check below would be true and we'll discard the whole
+                        * file cache which is not what was asked.
+                        */
+                       if (end_index == 0)
+                               break;
+
+                       end_index--;
+               }
 
                if (end_index >= start_index) {
                        unsigned long count = invalidate_mapping_pages(mapping,
index d26162e..388c2bb 100644 (file)
@@ -832,8 +832,27 @@ static bool vma_has_reserves(struct vm_area_struct *vma, long chg)
         * Only the process that called mmap() has reserves for
         * private mappings.
         */
-       if (is_vma_resv_set(vma, HPAGE_RESV_OWNER))
-               return true;
+       if (is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
+               /*
+                * Like the shared case above, a hole punch or truncate
+                * could have been performed on the private mapping.
+                * Examine the value of chg to determine if reserves
+                * actually exist or were previously consumed.
+                * Very Subtle - The value of chg comes from a previous
+                * call to vma_needs_reserves().  The reserve map for
+                * private mappings has different (opposite) semantics
+                * than that of shared mappings.  vma_needs_reserves()
+                * has already taken this difference in semantics into
+                * account.  Therefore, the meaning of chg is the same
+                * as in the shared case above.  Code could easily be
+                * combined, but keeping it separate draws attention to
+                * subtle differences.
+                */
+               if (chg)
+                       return false;
+               else
+                       return true;
+       }
 
        return false;
 }
@@ -1816,6 +1835,25 @@ static long __vma_reservation_common(struct hstate *h,
 
        if (vma->vm_flags & VM_MAYSHARE)
                return ret;
+       else if (is_vma_resv_set(vma, HPAGE_RESV_OWNER) && ret >= 0) {
+               /*
+                * In most cases, reserves always exist for private mappings.
+                * However, a file associated with mapping could have been
+                * hole punched or truncated after reserves were consumed.
+                * As subsequent fault on such a range will not use reserves.
+                * Subtle - The reserve map for private mappings has the
+                * opposite meaning than that of shared mappings.  If NO
+                * entry is in the reserve map, it means a reservation exists.
+                * If an entry exists in the reserve map, it means the
+                * reservation has already been consumed.  As a result, the
+                * return value of this routine is the opposite of the
+                * value returned from reserve map manipulation routines above.
+                */
+               if (ret)
+                       return 0;
+               else
+                       return 1;
+       }
        else
                return ret < 0 ? ret : 0;
 }
index 18b6a2b..28439ac 100644 (file)
@@ -763,8 +763,8 @@ static int kasan_mem_notifier(struct notifier_block *nb,
 
 static int __init kasan_memhotplug_init(void)
 {
-       pr_err("WARNING: KASAN doesn't support memory hot-add\n");
-       pr_err("Memory hot-add will be disabled\n");
+       pr_info("WARNING: KASAN doesn't support memory hot-add\n");
+       pr_info("Memory hot-add will be disabled\n");
 
        hotplug_memory_notifier(kasan_mem_notifier, 0);
 
index 58c69c9..75e7440 100644 (file)
@@ -1608,7 +1608,7 @@ static void memcg_oom_recover(struct mem_cgroup *memcg)
 
 static void mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int order)
 {
-       if (!current->memcg_may_oom || current->memcg_in_oom)
+       if (!current->memcg_may_oom)
                return;
        /*
         * We are in the middle of the charge context here, so we
index 9591614..59f5faf 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -667,6 +667,24 @@ static void lru_add_drain_per_cpu(struct work_struct *dummy)
 
 static DEFINE_PER_CPU(struct work_struct, lru_add_drain_work);
 
+/*
+ * lru_add_drain_wq is used to do lru_add_drain_all() from a WQ_MEM_RECLAIM
+ * workqueue, aiding in getting memory freed.
+ */
+static struct workqueue_struct *lru_add_drain_wq;
+
+static int __init lru_init(void)
+{
+       lru_add_drain_wq = alloc_workqueue("lru-add-drain", WQ_MEM_RECLAIM, 0);
+
+       if (WARN(!lru_add_drain_wq,
+               "Failed to create workqueue lru_add_drain_wq"))
+               return -ENOMEM;
+
+       return 0;
+}
+early_initcall(lru_init);
+
 void lru_add_drain_all(void)
 {
        static DEFINE_MUTEX(lock);
@@ -686,7 +704,7 @@ void lru_add_drain_all(void)
                    pagevec_count(&per_cpu(lru_deactivate_pvecs, cpu)) ||
                    need_activate_page_drain(cpu)) {
                        INIT_WORK(work, lru_add_drain_per_cpu);
-                       schedule_work_on(cpu, work);
+                       queue_work_on(cpu, lru_add_drain_wq, work);
                        cpumask_set_cpu(cpu, &has_work);
                }
        }
index 0d457e7..c99463a 100644 (file)
@@ -252,7 +252,10 @@ static inline void free_swap_cache(struct page *page)
 void free_page_and_swap_cache(struct page *page)
 {
        free_swap_cache(page);
-       put_page(page);
+       if (is_huge_zero_page(page))
+               put_huge_zero_page();
+       else
+               put_page(page);
 }
 
 /*
index dcea4f4..c18080a 100644 (file)
@@ -279,6 +279,8 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
         * change from under us.
         */
        list_for_each_entry(v, &vg->vlan_list, vlist) {
+               if (!br_vlan_should_use(v))
+                       continue;
                f = __br_fdb_get(br, br->dev->dev_addr, v->vid);
                if (f && f->is_local && !f->dst)
                        fdb_delete_local(br, NULL, f);
index 5cfd26a..1cd2ec0 100644 (file)
@@ -309,8 +309,8 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm)
        __scm_destroy(scm);
 }
 
-static int do_set_attach_filter(struct socket *sock, int level, int optname,
-                               char __user *optval, unsigned int optlen)
+/* allocate a 64-bit sock_fprog on the user stack for duration of syscall. */
+struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval)
 {
        struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval;
        struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog));
@@ -323,6 +323,19 @@ static int do_set_attach_filter(struct socket *sock, int level, int optname,
            __get_user(ptr, &fprog32->filter) ||
            __put_user(len, &kfprog->len) ||
            __put_user(compat_ptr(ptr), &kfprog->filter))
+               return NULL;
+
+       return kfprog;
+}
+EXPORT_SYMBOL_GPL(get_compat_bpf_fprog);
+
+static int do_set_attach_filter(struct socket *sock, int level, int optname,
+                               char __user *optval, unsigned int optlen)
+{
+       struct sock_fprog __user *kfprog;
+
+       kfprog = get_compat_bpf_fprog(optval);
+       if (!kfprog)
                return -EFAULT;
 
        return sock_setsockopt(sock, level, optname, (char __user *)kfprog,
@@ -354,7 +367,8 @@ static int do_set_sock_timeout(struct socket *sock, int level,
 static int compat_sock_setsockopt(struct socket *sock, int level, int optname,
                                char __user *optval, unsigned int optlen)
 {
-       if (optname == SO_ATTACH_FILTER)
+       if (optname == SO_ATTACH_FILTER ||
+           optname == SO_ATTACH_REUSEPORT_CBPF)
                return do_set_attach_filter(sock, level, optname,
                                            optval, optlen);
        if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
index f96ee8b..be873e4 100644 (file)
@@ -47,6 +47,7 @@ nla_put_failure:
  * @xstats_type: TLV type for backward compatibility xstats TLV
  * @lock: statistics lock
  * @d: dumping handle
+ * @padattr: padding attribute
  *
  * Initializes the dumping handle, grabs the statistic lock and appends
  * an empty TLV header to the socket buffer for use a container for all
@@ -87,6 +88,7 @@ EXPORT_SYMBOL(gnet_stats_start_copy_compat);
  * @type: TLV type for top level statistic TLV
  * @lock: statistics lock
  * @d: dumping handle
+ * @padattr: padding attribute
  *
  * Initializes the dumping handle, grabs the statistic lock and appends
  * an empty TLV header to the socket buffer for use a container for all
index 2b3f76f..7a0b616 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/jiffies.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_net.h>
 
 #include "net-sysfs.h"
 
index d56c055..0ff31d9 100644 (file)
@@ -1618,12 +1618,12 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                }
        }
 
-       if (rcu_access_pointer(sk->sk_filter)) {
-               if (udp_lib_checksum_complete(skb))
+       if (rcu_access_pointer(sk->sk_filter) &&
+           udp_lib_checksum_complete(skb))
                        goto csum_error;
-               if (sk_filter(sk, skb))
-                       goto drop;
-       }
+
+       if (sk_filter(sk, skb))
+               goto drop;
 
        udp_csum_pull_header(skb);
        if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
index f4ac284..fdc9de2 100644 (file)
@@ -1256,6 +1256,8 @@ static int ip6gre_tap_init(struct net_device *dev)
        if (ret)
                return ret;
 
+       dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+
        tunnel = netdev_priv(dev);
 
        ip6gre_tnl_link_config(tunnel, 1);
@@ -1289,6 +1291,7 @@ static void ip6gre_tap_setup(struct net_device *dev)
 
        dev->features |= NETIF_F_NETNS_LOCAL;
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+       dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 }
 
 static bool ip6gre_netlink_encap_parms(struct nlattr *data[],
index cbf127a..635b8d3 100644 (file)
@@ -1071,17 +1071,12 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
                                         const struct in6_addr *final_dst)
 {
        struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie);
-       int err;
 
        dst = ip6_sk_dst_check(sk, dst, fl6);
+       if (!dst)
+               dst = ip6_dst_lookup_flow(sk, fl6, final_dst);
 
-       err = ip6_dst_lookup_tail(sock_net(sk), sk, &dst, fl6);
-       if (err)
-               return ERR_PTR(err);
-       if (final_dst)
-               fl6->daddr = *final_dst;
-
-       return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
+       return dst;
 }
 EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow);
 
index 6989c70..4a84b5a 100644 (file)
@@ -33,6 +33,7 @@ static bool nf_dup_ipv6_route(struct net *net, struct sk_buff *skb,
        fl6.daddr = *gw;
        fl6.flowlabel = (__force __be32)(((iph->flow_lbl[0] & 0xF) << 16) |
                        (iph->flow_lbl[1] << 8) | iph->flow_lbl[2]);
+       fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH;
        dst = ip6_route_output(net, NULL, &fl6);
        if (dst->error) {
                dst_release(dst);
index 79e33e0..f36c2d0 100644 (file)
@@ -1721,7 +1721,9 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
        destp = ntohs(inet->inet_dport);
        srcp  = ntohs(inet->inet_sport);
 
-       if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
+       if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
+           icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
+           icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
                timer_active    = 1;
                timer_expires   = icsk->icsk_timeout;
        } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
index 2da1896..f421c9f 100644 (file)
@@ -653,12 +653,12 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                }
        }
 
-       if (rcu_access_pointer(sk->sk_filter)) {
-               if (udp_lib_checksum_complete(skb))
-                       goto csum_error;
-               if (sk_filter(sk, skb))
-                       goto drop;
-       }
+       if (rcu_access_pointer(sk->sk_filter) &&
+           udp_lib_checksum_complete(skb))
+               goto csum_error;
+
+       if (sk_filter(sk, skb))
+               goto drop;
 
        udp_csum_pull_header(skb);
        if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
index 6edfa99..1e40dac 100644 (file)
@@ -1581,7 +1581,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
        /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
        tunnel->encap = encap;
        if (encap == L2TP_ENCAPTYPE_UDP) {
-               struct udp_tunnel_sock_cfg udp_cfg;
+               struct udp_tunnel_sock_cfg udp_cfg = { };
 
                udp_cfg.sk_user_data = tunnel;
                udp_cfg.encap_type = UDP_ENCAP_L2TPINUDP;
index 4c6404e..21b1fdf 100644 (file)
@@ -161,6 +161,10 @@ void mesh_sta_cleanup(struct sta_info *sta)
                del_timer_sync(&sta->mesh->plink_timer);
        }
 
+       /* make sure no readers can access nexthop sta from here on */
+       mesh_path_flush_by_nexthop(sta);
+       synchronize_net();
+
        if (changed)
                ieee80211_mbss_info_change_notify(sdata, changed);
 }
index c8b8ccc..78b0ef3 100644 (file)
@@ -280,7 +280,7 @@ struct ieee80211_fast_tx {
        u8 sa_offs, da_offs, pn_offs;
        u8 band;
        u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
-              sizeof(rfc1042_header)];
+              sizeof(rfc1042_header)] __aligned(2);
 
        struct rcu_head rcu_head;
 };
index 2cb3c62..096a451 100644 (file)
@@ -762,7 +762,7 @@ static int expire_quiescent_template(struct netns_ipvs *ipvs,
  *     If available, return 1, otherwise invalidate this connection
  *     template and return 0.
  */
-int ip_vs_check_template(struct ip_vs_conn *ct)
+int ip_vs_check_template(struct ip_vs_conn *ct, struct ip_vs_dest *cdest)
 {
        struct ip_vs_dest *dest = ct->dest;
        struct netns_ipvs *ipvs = ct->ipvs;
@@ -772,7 +772,8 @@ int ip_vs_check_template(struct ip_vs_conn *ct)
         */
        if ((dest == NULL) ||
            !(dest->flags & IP_VS_DEST_F_AVAILABLE) ||
-           expire_quiescent_template(ipvs, dest)) {
+           expire_quiescent_template(ipvs, dest) ||
+           (cdest && (dest != cdest))) {
                IP_VS_DBG_BUF(9, "check_template: dest not available for "
                              "protocol %s s:%s:%d v:%s:%d "
                              "-> d:%s:%d\n",
index 1207f20..2c1b498 100644 (file)
@@ -321,7 +321,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
 
        /* Check if a template already exists */
        ct = ip_vs_ct_in_get(&param);
-       if (!ct || !ip_vs_check_template(ct)) {
+       if (!ct || !ip_vs_check_template(ct, NULL)) {
                struct ip_vs_scheduler *sched;
 
                /*
@@ -1154,7 +1154,8 @@ struct ip_vs_conn *ip_vs_new_conn_out(struct ip_vs_service *svc,
                                                  vport, &param) < 0)
                        return NULL;
                ct = ip_vs_ct_in_get(&param);
-               if (!ct) {
+               /* check if template exists and points to the same dest */
+               if (!ct || !ip_vs_check_template(ct, dest)) {
                        ct = ip_vs_conn_new(&param, dest->af, daddr, dport,
                                            IP_VS_CONN_F_TEMPLATE, dest, 0);
                        if (!ct) {
index 883c691..19efeba 100644 (file)
@@ -632,6 +632,7 @@ static int __init nf_conntrack_ftp_init(void)
                        if (ret) {
                                pr_err("failed to register helper for pf: %d port: %d\n",
                                       ftp[i][j].tuple.src.l3num, ports[i]);
+                               ports_c = i;
                                nf_conntrack_ftp_fini();
                                return ret;
                        }
index f703adb..196cb39 100644 (file)
@@ -361,9 +361,10 @@ EXPORT_SYMBOL_GPL(nf_ct_helper_log);
 
 int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 {
-       int ret = 0;
-       struct nf_conntrack_helper *cur;
+       struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) };
        unsigned int h = helper_hash(&me->tuple);
+       struct nf_conntrack_helper *cur;
+       int ret = 0;
 
        BUG_ON(me->expect_policy == NULL);
        BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES);
@@ -371,9 +372,7 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 
        mutex_lock(&nf_ct_helper_mutex);
        hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) {
-               if (strncmp(cur->name, me->name, NF_CT_HELPER_NAME_LEN) == 0 &&
-                   cur->tuple.src.l3num == me->tuple.src.l3num &&
-                   cur->tuple.dst.protonum == me->tuple.dst.protonum) {
+               if (nf_ct_tuple_src_mask_cmp(&cur->tuple, &me->tuple, &mask)) {
                        ret = -EEXIST;
                        goto out;
                }
index 8b6da27..f97ac61 100644 (file)
@@ -271,6 +271,7 @@ static int __init nf_conntrack_irc_init(void)
                if (ret) {
                        pr_err("failed to register helper for pf: %u port: %u\n",
                               irc[i].tuple.src.l3num, ports[i]);
+                       ports_c = i;
                        nf_conntrack_irc_fini();
                        return ret;
                }
index 7523a57..3fcbaab 100644 (file)
@@ -223,6 +223,7 @@ static int __init nf_conntrack_sane_init(void)
                        if (ret) {
                                pr_err("failed to register helper for pf: %d port: %d\n",
                                       sane[i][j].tuple.src.l3num, ports[i]);
+                               ports_c = i;
                                nf_conntrack_sane_fini();
                                return ret;
                        }
index 3e06402..f72ba55 100644 (file)
@@ -1669,6 +1669,7 @@ static int __init nf_conntrack_sip_init(void)
                        if (ret) {
                                pr_err("failed to register helper for pf: %u port: %u\n",
                                       sip[i][j].tuple.src.l3num, ports[i]);
+                               ports_c = i;
                                nf_conntrack_sip_fini();
                                return ret;
                        }
index f87e84e..c026c47 100644 (file)
@@ -487,8 +487,6 @@ static struct ctl_table nf_ct_sysctl_table[] = {
        { }
 };
 
-#define NET_NF_CONNTRACK_MAX 2089
-
 static struct ctl_table nf_ct_netfilter_table[] = {
        {
                .procname       = "nf_conntrack_max",
index 36f9640..2e65b54 100644 (file)
@@ -142,6 +142,7 @@ static int __init nf_conntrack_tftp_init(void)
                        if (ret) {
                                pr_err("failed to register helper for pf: %u port: %u\n",
                                       tftp[i][j].tuple.src.l3num, ports[i]);
+                               ports_c = i;
                                nf_conntrack_tftp_fini();
                                return ret;
                        }
index 5baa8e2..b19ad20 100644 (file)
  * Once the queue is registered it must reinject all packets it
  * receives, no matter what.
  */
-static const struct nf_queue_handler __rcu *queue_handler __read_mostly;
 
 /* return EBUSY when somebody else is registered, return EEXIST if the
  * same handler is registered, return 0 in case of success. */
-void nf_register_queue_handler(const struct nf_queue_handler *qh)
+void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh)
 {
        /* should never happen, we only have one queueing backend in kernel */
-       WARN_ON(rcu_access_pointer(queue_handler));
-       rcu_assign_pointer(queue_handler, qh);
+       WARN_ON(rcu_access_pointer(net->nf.queue_handler));
+       rcu_assign_pointer(net->nf.queue_handler, qh);
 }
 EXPORT_SYMBOL(nf_register_queue_handler);
 
 /* The caller must flush their queue before this */
-void nf_unregister_queue_handler(void)
+void nf_unregister_queue_handler(struct net *net)
 {
-       RCU_INIT_POINTER(queue_handler, NULL);
-       synchronize_rcu();
+       RCU_INIT_POINTER(net->nf.queue_handler, NULL);
 }
 EXPORT_SYMBOL(nf_unregister_queue_handler);
 
@@ -103,7 +101,7 @@ void nf_queue_nf_hook_drop(struct net *net, struct nf_hook_ops *ops)
        const struct nf_queue_handler *qh;
 
        rcu_read_lock();
-       qh = rcu_dereference(queue_handler);
+       qh = rcu_dereference(net->nf.queue_handler);
        if (qh)
                qh->nf_hook_drop(net, ops);
        rcu_read_unlock();
@@ -122,9 +120,10 @@ int nf_queue(struct sk_buff *skb,
        struct nf_queue_entry *entry = NULL;
        const struct nf_afinfo *afinfo;
        const struct nf_queue_handler *qh;
+       struct net *net = state->net;
 
        /* QUEUE == DROP if no one is waiting, to be safe. */
-       qh = rcu_dereference(queue_handler);
+       qh = rcu_dereference(net->nf.queue_handler);
        if (!qh) {
                status = -ESRCH;
                goto err;
index 4d292b9..7b7aa87 100644 (file)
@@ -2647,6 +2647,8 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk,
        /* Only accept unspec with dump */
        if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
                return -EAFNOSUPPORT;
+       if (!nla[NFTA_SET_TABLE])
+               return -EINVAL;
 
        set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
        if (IS_ERR(set))
index aa93877..5d36a09 100644 (file)
@@ -557,7 +557,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
 
        if (entskb->tstamp.tv64) {
                struct nfqnl_msg_packet_timestamp ts;
-               struct timespec64 kts = ktime_to_timespec64(skb->tstamp);
+               struct timespec64 kts = ktime_to_timespec64(entskb->tstamp);
 
                ts.sec = cpu_to_be64(kts.tv_sec);
                ts.usec = cpu_to_be64(kts.tv_nsec / NSEC_PER_USEC);
@@ -1482,21 +1482,29 @@ static int __net_init nfnl_queue_net_init(struct net *net)
                         net->nf.proc_netfilter, &nfqnl_file_ops))
                return -ENOMEM;
 #endif
+       nf_register_queue_handler(net, &nfqh);
        return 0;
 }
 
 static void __net_exit nfnl_queue_net_exit(struct net *net)
 {
+       nf_unregister_queue_handler(net);
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter);
 #endif
 }
 
+static void nfnl_queue_net_exit_batch(struct list_head *net_exit_list)
+{
+       synchronize_rcu();
+}
+
 static struct pernet_operations nfnl_queue_net_ops = {
-       .init   = nfnl_queue_net_init,
-       .exit   = nfnl_queue_net_exit,
-       .id     = &nfnl_queue_net_id,
-       .size   = sizeof(struct nfnl_queue_net),
+       .init           = nfnl_queue_net_init,
+       .exit           = nfnl_queue_net_exit,
+       .exit_batch     = nfnl_queue_net_exit_batch,
+       .id             = &nfnl_queue_net_id,
+       .size           = sizeof(struct nfnl_queue_net),
 };
 
 static int __init nfnetlink_queue_init(void)
@@ -1517,7 +1525,6 @@ static int __init nfnetlink_queue_init(void)
        }
 
        register_netdevice_notifier(&nfqnl_dev_notifier);
-       nf_register_queue_handler(&nfqh);
        return status;
 
 cleanup_netlink_notifier:
@@ -1529,7 +1536,6 @@ out:
 
 static void __exit nfnetlink_queue_fini(void)
 {
-       nf_unregister_queue_handler();
        unregister_netdevice_notifier(&nfqnl_dev_notifier);
        nfnetlink_subsys_unregister(&nfqnl_subsys);
        netlink_unregister_notifier(&nfqnl_rtnl_notifier);
index c69c892..2675d58 100644 (file)
@@ -612,7 +612,7 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems,
                return -EINVAL;
 
        if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
-           target_offset + sizeof(struct compat_xt_standard_target) != next_offset)
+           COMPAT_XT_ALIGN(target_offset + sizeof(struct compat_xt_standard_target)) != next_offset)
                return -EINVAL;
 
        /* compat_xt_entry match has less strict aligment requirements,
@@ -694,7 +694,7 @@ int xt_check_entry_offsets(const void *base,
                return -EINVAL;
 
        if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
-           target_offset + sizeof(struct xt_standard_target) != next_offset)
+           XT_ALIGN(target_offset + sizeof(struct xt_standard_target)) != next_offset)
                return -EINVAL;
 
        return xt_check_entry_match(elems, base + target_offset,
index 4040eb9..9bff6ef 100644 (file)
@@ -93,6 +93,7 @@
 #include <net/inet_common.h>
 #endif
 #include <linux/bpf.h>
+#include <net/compat.h>
 
 #include "internal.h"
 
@@ -3940,6 +3941,27 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 }
 
 
+#ifdef CONFIG_COMPAT
+static int compat_packet_setsockopt(struct socket *sock, int level, int optname,
+                                   char __user *optval, unsigned int optlen)
+{
+       struct packet_sock *po = pkt_sk(sock->sk);
+
+       if (level != SOL_PACKET)
+               return -ENOPROTOOPT;
+
+       if (optname == PACKET_FANOUT_DATA &&
+           po->fanout && po->fanout->type == PACKET_FANOUT_CBPF) {
+               optval = (char __user *)get_compat_bpf_fprog(optval);
+               if (!optval)
+                       return -EFAULT;
+               optlen = sizeof(struct sock_fprog);
+       }
+
+       return packet_setsockopt(sock, level, optname, optval, optlen);
+}
+#endif
+
 static int packet_notifier(struct notifier_block *this,
                           unsigned long msg, void *ptr)
 {
@@ -4416,6 +4438,9 @@ static const struct proto_ops packet_ops = {
        .shutdown =     sock_no_shutdown,
        .setsockopt =   packet_setsockopt,
        .getsockopt =   packet_getsockopt,
+#ifdef CONFIG_COMPAT
+       .compat_setsockopt = compat_packet_setsockopt,
+#endif
        .sendmsg =      packet_sendmsg,
        .recvmsg =      packet_recvmsg,
        .mmap =         packet_mmap,
index 80256b0..387df5f 100644 (file)
@@ -74,6 +74,7 @@ enum {
        RDS_CONN_CONNECTING,
        RDS_CONN_DISCONNECTING,
        RDS_CONN_UP,
+       RDS_CONN_RESETTING,
        RDS_CONN_ERROR,
 };
 
@@ -813,6 +814,7 @@ void rds_connect_worker(struct work_struct *);
 void rds_shutdown_worker(struct work_struct *);
 void rds_send_worker(struct work_struct *);
 void rds_recv_worker(struct work_struct *);
+void rds_connect_path_complete(struct rds_connection *conn, int curr);
 void rds_connect_complete(struct rds_connection *conn);
 
 /* transport.c */
index c0be1ec..8413f6c 100644 (file)
@@ -561,5 +561,7 @@ void rds_inc_info_copy(struct rds_incoming *inc,
                minfo.fport = inc->i_hdr.h_dport;
        }
 
+       minfo.flags = 0;
+
        rds_info_copy(iter, &minfo, sizeof(minfo));
 }
index c9cdb35..b1962f8 100644 (file)
@@ -99,6 +99,7 @@ void rds_send_reset(struct rds_connection *conn)
        list_splice_init(&conn->c_retrans, &conn->c_send_queue);
        spin_unlock_irqrestore(&conn->c_lock, flags);
 }
+EXPORT_SYMBOL_GPL(rds_send_reset);
 
 static int acquire_in_xmit(struct rds_connection *conn)
 {
index 86187da..74ee126 100644 (file)
@@ -126,9 +126,81 @@ void rds_tcp_restore_callbacks(struct socket *sock,
 }
 
 /*
- * This is the only path that sets tc->t_sock.  Send and receive trust that
- * it is set.  The RDS_CONN_UP bit protects those paths from being
- * called while it isn't set.
+ * rds_tcp_reset_callbacks() switches the to the new sock and
+ * returns the existing tc->t_sock.
+ *
+ * The only functions that set tc->t_sock are rds_tcp_set_callbacks
+ * and rds_tcp_reset_callbacks.  Send and receive trust that
+ * it is set.  The absence of RDS_CONN_UP bit protects those paths
+ * from being called while it isn't set.
+ */
+void rds_tcp_reset_callbacks(struct socket *sock,
+                            struct rds_connection *conn)
+{
+       struct rds_tcp_connection *tc = conn->c_transport_data;
+       struct socket *osock = tc->t_sock;
+
+       if (!osock)
+               goto newsock;
+
+       /* Need to resolve a duelling SYN between peers.
+        * We have an outstanding SYN to this peer, which may
+        * potentially have transitioned to the RDS_CONN_UP state,
+        * so we must quiesce any send threads before resetting
+        * c_transport_data. We quiesce these threads by setting
+        * c_state to something other than RDS_CONN_UP, and then
+        * waiting for any existing threads in rds_send_xmit to
+        * complete release_in_xmit(). (Subsequent threads entering
+        * rds_send_xmit() will bail on !rds_conn_up().
+        *
+        * However an incoming syn-ack at this point would end up
+        * marking the conn as RDS_CONN_UP, and would again permit
+        * rds_send_xmi() threads through, so ideally we would
+        * synchronize on RDS_CONN_UP after lock_sock(), but cannot
+        * do that: waiting on !RDS_IN_XMIT after lock_sock() may
+        * end up deadlocking with tcp_sendmsg(), and the RDS_IN_XMIT
+        * would not get set. As a result, we set c_state to
+        * RDS_CONN_RESETTTING, to ensure that rds_tcp_state_change
+        * cannot mark rds_conn_path_up() in the window before lock_sock()
+        */
+       atomic_set(&conn->c_state, RDS_CONN_RESETTING);
+       wait_event(conn->c_waitq, !test_bit(RDS_IN_XMIT, &conn->c_flags));
+       lock_sock(osock->sk);
+       /* reset receive side state for rds_tcp_data_recv() for osock  */
+       if (tc->t_tinc) {
+               rds_inc_put(&tc->t_tinc->ti_inc);
+               tc->t_tinc = NULL;
+       }
+       tc->t_tinc_hdr_rem = sizeof(struct rds_header);
+       tc->t_tinc_data_rem = 0;
+       tc->t_sock = NULL;
+
+       write_lock_bh(&osock->sk->sk_callback_lock);
+
+       osock->sk->sk_user_data = NULL;
+       osock->sk->sk_data_ready = tc->t_orig_data_ready;
+       osock->sk->sk_write_space = tc->t_orig_write_space;
+       osock->sk->sk_state_change = tc->t_orig_state_change;
+       write_unlock_bh(&osock->sk->sk_callback_lock);
+       release_sock(osock->sk);
+       sock_release(osock);
+newsock:
+       rds_send_reset(conn);
+       lock_sock(sock->sk);
+       write_lock_bh(&sock->sk->sk_callback_lock);
+       tc->t_sock = sock;
+       sock->sk->sk_user_data = conn;
+       sock->sk->sk_data_ready = rds_tcp_data_ready;
+       sock->sk->sk_write_space = rds_tcp_write_space;
+       sock->sk->sk_state_change = rds_tcp_state_change;
+
+       write_unlock_bh(&sock->sk->sk_callback_lock);
+       release_sock(sock->sk);
+}
+
+/* Add tc to rds_tcp_tc_list and set tc->t_sock. See comments
+ * above rds_tcp_reset_callbacks for notes about synchronization
+ * with data path
  */
 void rds_tcp_set_callbacks(struct socket *sock, struct rds_connection *conn)
 {
index 41c2283..ec0602b 100644 (file)
@@ -50,6 +50,7 @@ struct rds_tcp_statistics {
 void rds_tcp_tune(struct socket *sock);
 void rds_tcp_nonagle(struct socket *sock);
 void rds_tcp_set_callbacks(struct socket *sock, struct rds_connection *conn);
+void rds_tcp_reset_callbacks(struct socket *sock, struct rds_connection *conn);
 void rds_tcp_restore_callbacks(struct socket *sock,
                               struct rds_tcp_connection *tc);
 u32 rds_tcp_snd_nxt(struct rds_tcp_connection *tc);
index fb82e0a..fba13d0 100644 (file)
@@ -60,7 +60,7 @@ void rds_tcp_state_change(struct sock *sk)
                case TCP_SYN_RECV:
                        break;
                case TCP_ESTABLISHED:
-                       rds_connect_complete(conn);
+                       rds_connect_path_complete(conn, RDS_CONN_CONNECTING);
                        break;
                case TCP_CLOSE_WAIT:
                case TCP_CLOSE:
index 4bf4bef..686b1d0 100644 (file)
@@ -78,7 +78,6 @@ int rds_tcp_accept_one(struct socket *sock)
        struct inet_sock *inet;
        struct rds_tcp_connection *rs_tcp = NULL;
        int conn_state;
-       struct sock *nsk;
 
        if (!sock) /* module unload or netns delete in progress */
                return -ENETUNREACH;
@@ -136,26 +135,21 @@ int rds_tcp_accept_one(struct socket *sock)
                    !conn->c_outgoing) {
                        goto rst_nsk;
                } else {
-                       atomic_set(&conn->c_state, RDS_CONN_CONNECTING);
-                       wait_event(conn->c_waitq,
-                                  !test_bit(RDS_IN_XMIT, &conn->c_flags));
-                       rds_tcp_restore_callbacks(rs_tcp->t_sock, rs_tcp);
+                       rds_tcp_reset_callbacks(new_sock, conn);
                        conn->c_outgoing = 0;
+                       /* rds_connect_path_complete() marks RDS_CONN_UP */
+                       rds_connect_path_complete(conn, RDS_CONN_DISCONNECTING);
                }
+       } else {
+               rds_tcp_set_callbacks(new_sock, conn);
+               rds_connect_path_complete(conn, RDS_CONN_CONNECTING);
        }
-       rds_tcp_set_callbacks(new_sock, conn);
-       rds_connect_complete(conn); /* marks RDS_CONN_UP */
        new_sock = NULL;
        ret = 0;
        goto out;
 rst_nsk:
        /* reset the newly returned accept sock and bail */
-       nsk = new_sock->sk;
-       rds_tcp_stats_inc(s_tcp_listen_closed_stale);
-       nsk->sk_user_data = NULL;
-       nsk->sk_prot->disconnect(nsk, 0);
-       tcp_done(nsk);
-       new_sock = NULL;
+       kernel_sock_shutdown(new_sock, SHUT_RDWR);
        ret = 0;
 out:
        if (rs_tcp)
index 454aa6d..4a32304 100644 (file)
@@ -71,9 +71,9 @@
 struct workqueue_struct *rds_wq;
 EXPORT_SYMBOL_GPL(rds_wq);
 
-void rds_connect_complete(struct rds_connection *conn)
+void rds_connect_path_complete(struct rds_connection *conn, int curr)
 {
-       if (!rds_conn_transition(conn, RDS_CONN_CONNECTING, RDS_CONN_UP)) {
+       if (!rds_conn_transition(conn, curr, RDS_CONN_UP)) {
                printk(KERN_WARNING "%s: Cannot transition to state UP, "
                                "current state is %d\n",
                                __func__,
@@ -90,6 +90,12 @@ void rds_connect_complete(struct rds_connection *conn)
        queue_delayed_work(rds_wq, &conn->c_send_w, 0);
        queue_delayed_work(rds_wq, &conn->c_recv_w, 0);
 }
+EXPORT_SYMBOL_GPL(rds_connect_path_complete);
+
+void rds_connect_complete(struct rds_connection *conn)
+{
+       rds_connect_path_complete(conn, RDS_CONN_CONNECTING);
+}
 EXPORT_SYMBOL_GPL(rds_connect_complete);
 
 /*
index 6b726a0..bab56ed 100644 (file)
@@ -1162,9 +1162,7 @@ static int rxkad_init(void)
        /* pin the cipher we need so that the crypto layer doesn't invoke
         * keventd to go get it */
        rxkad_ci = crypto_alloc_skcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(rxkad_ci))
-               return PTR_ERR(rxkad_ci);
-       return 0;
+       return PTR_ERR_OR_ZERO(rxkad_ci);
 }
 
 /*
index b884dae..c557789 100644 (file)
@@ -38,7 +38,7 @@ struct tcf_police {
        bool                    peak_present;
 };
 #define to_police(pc)  \
-       container_of(pc, struct tcf_police, common)
+       container_of(pc->priv, struct tcf_police, common)
 
 #define POL_TAB_MASK     15
 
@@ -119,14 +119,12 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
                                 struct nlattr *est, struct tc_action *a,
                                 int ovr, int bind)
 {
-       unsigned int h;
        int ret = 0, err;
        struct nlattr *tb[TCA_POLICE_MAX + 1];
        struct tc_police *parm;
        struct tcf_police *police;
        struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
        struct tc_action_net *tn = net_generic(net, police_net_id);
-       struct tcf_hashinfo *hinfo = tn->hinfo;
        int size;
 
        if (nla == NULL)
@@ -145,7 +143,7 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
 
        if (parm->index) {
                if (tcf_hash_search(tn, a, parm->index)) {
-                       police = to_police(a->priv);
+                       police = to_police(a);
                        if (bind) {
                                police->tcf_bindcnt += 1;
                                police->tcf_refcnt += 1;
@@ -156,16 +154,15 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
                        /* not replacing */
                        return -EEXIST;
                }
+       } else {
+               ret = tcf_hash_create(tn, parm->index, NULL, a,
+                                     sizeof(*police), bind, false);
+               if (ret)
+                       return ret;
+               ret = ACT_P_CREATED;
        }
 
-       police = kzalloc(sizeof(*police), GFP_KERNEL);
-       if (police == NULL)
-               return -ENOMEM;
-       ret = ACT_P_CREATED;
-       police->tcf_refcnt = 1;
-       spin_lock_init(&police->tcf_lock);
-       if (bind)
-               police->tcf_bindcnt = 1;
+       police = to_police(a);
 override:
        if (parm->rate.rate) {
                err = -ENOMEM;
@@ -237,16 +234,8 @@ override:
                return ret;
 
        police->tcfp_t_c = ktime_get_ns();
-       police->tcf_index = parm->index ? parm->index :
-               tcf_hash_new_index(tn);
-       police->tcf_tm.install = jiffies;
-       police->tcf_tm.lastuse = jiffies;
-       h = tcf_hash(police->tcf_index, POL_TAB_MASK);
-       spin_lock_bh(&hinfo->lock);
-       hlist_add_head(&police->tcf_head, &hinfo->htab[h]);
-       spin_unlock_bh(&hinfo->lock);
+       tcf_hash_insert(tn, a);
 
-       a->priv = police;
        return ret;
 
 failure_unlock:
@@ -255,7 +244,7 @@ failure:
        qdisc_put_rtab(P_tab);
        qdisc_put_rtab(R_tab);
        if (ret == ACT_P_CREATED)
-               kfree(police);
+               tcf_hash_cleanup(a, est);
        return err;
 }
 
index 730aaca..b3b7978 100644 (file)
@@ -171,7 +171,7 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, unsigned long cookie)
        struct tc_cls_flower_offload offload = {0};
        struct tc_to_netdev tc;
 
-       if (!tc_should_offload(dev, 0))
+       if (!tc_should_offload(dev, tp, 0))
                return;
 
        offload.command = TC_CLSFLOWER_DESTROY;
@@ -194,7 +194,7 @@ static void fl_hw_replace_filter(struct tcf_proto *tp,
        struct tc_cls_flower_offload offload = {0};
        struct tc_to_netdev tc;
 
-       if (!tc_should_offload(dev, flags))
+       if (!tc_should_offload(dev, tp, flags))
                return;
 
        offload.command = TC_CLSFLOWER_REPLACE;
@@ -216,7 +216,7 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
        struct tc_cls_flower_offload offload = {0};
        struct tc_to_netdev tc;
 
-       if (!tc_should_offload(dev, 0))
+       if (!tc_should_offload(dev, tp, 0))
                return;
 
        offload.command = TC_CLSFLOWER_STATS;
index 079b43b..ffe593e 100644 (file)
@@ -440,7 +440,7 @@ static void u32_remove_hw_knode(struct tcf_proto *tp, u32 handle)
        offload.type = TC_SETUP_CLSU32;
        offload.cls_u32 = &u32_offload;
 
-       if (tc_should_offload(dev, 0)) {
+       if (tc_should_offload(dev, tp, 0)) {
                offload.cls_u32->command = TC_CLSU32_DELETE_KNODE;
                offload.cls_u32->knode.handle = handle;
                dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
@@ -457,20 +457,21 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp,
        struct tc_to_netdev offload;
        int err;
 
+       if (!tc_should_offload(dev, tp, flags))
+               return tc_skip_sw(flags) ? -EINVAL : 0;
+
        offload.type = TC_SETUP_CLSU32;
        offload.cls_u32 = &u32_offload;
 
-       if (tc_should_offload(dev, flags)) {
-               offload.cls_u32->command = TC_CLSU32_NEW_HNODE;
-               offload.cls_u32->hnode.divisor = h->divisor;
-               offload.cls_u32->hnode.handle = h->handle;
-               offload.cls_u32->hnode.prio = h->prio;
+       offload.cls_u32->command = TC_CLSU32_NEW_HNODE;
+       offload.cls_u32->hnode.divisor = h->divisor;
+       offload.cls_u32->hnode.handle = h->handle;
+       offload.cls_u32->hnode.prio = h->prio;
 
-               err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-                                                   tp->protocol, &offload);
-               if (tc_skip_sw(flags))
-                       return err;
-       }
+       err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+                                           tp->protocol, &offload);
+       if (tc_skip_sw(flags))
+               return err;
 
        return 0;
 }
@@ -484,7 +485,7 @@ static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
        offload.type = TC_SETUP_CLSU32;
        offload.cls_u32 = &u32_offload;
 
-       if (tc_should_offload(dev, 0)) {
+       if (tc_should_offload(dev, tp, 0)) {
                offload.cls_u32->command = TC_CLSU32_DELETE_HNODE;
                offload.cls_u32->hnode.divisor = h->divisor;
                offload.cls_u32->hnode.handle = h->handle;
@@ -507,27 +508,28 @@ static int u32_replace_hw_knode(struct tcf_proto *tp,
        offload.type = TC_SETUP_CLSU32;
        offload.cls_u32 = &u32_offload;
 
-       if (tc_should_offload(dev, flags)) {
-               offload.cls_u32->command = TC_CLSU32_REPLACE_KNODE;
-               offload.cls_u32->knode.handle = n->handle;
-               offload.cls_u32->knode.fshift = n->fshift;
+       if (!tc_should_offload(dev, tp, flags))
+               return tc_skip_sw(flags) ? -EINVAL : 0;
+
+       offload.cls_u32->command = TC_CLSU32_REPLACE_KNODE;
+       offload.cls_u32->knode.handle = n->handle;
+       offload.cls_u32->knode.fshift = n->fshift;
 #ifdef CONFIG_CLS_U32_MARK
-               offload.cls_u32->knode.val = n->val;
-               offload.cls_u32->knode.mask = n->mask;
+       offload.cls_u32->knode.val = n->val;
+       offload.cls_u32->knode.mask = n->mask;
 #else
-               offload.cls_u32->knode.val = 0;
-               offload.cls_u32->knode.mask = 0;
+       offload.cls_u32->knode.val = 0;
+       offload.cls_u32->knode.mask = 0;
 #endif
-               offload.cls_u32->knode.sel = &n->sel;
-               offload.cls_u32->knode.exts = &n->exts;
-               if (n->ht_down)
-                       offload.cls_u32->knode.link_handle = n->ht_down->handle;
-
-               err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-                                                   tp->protocol, &offload);
-               if (tc_skip_sw(flags))
-                       return err;
-       }
+       offload.cls_u32->knode.sel = &n->sel;
+       offload.cls_u32->knode.exts = &n->exts;
+       if (n->ht_down)
+               offload.cls_u32->knode.link_handle = n->ht_down->handle;
+
+       err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+                                           tp->protocol, &offload);
+       if (tc_skip_sw(flags))
+               return err;
 
        return 0;
 }
@@ -863,7 +865,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
        if (tb[TCA_U32_FLAGS]) {
                flags = nla_get_u32(tb[TCA_U32_FLAGS]);
                if (!tc_flags_valid(flags))
-                       return err;
+                       return -EINVAL;
        }
 
        n = (struct tc_u_knode *)*arg;
@@ -921,11 +923,17 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
                ht->divisor = divisor;
                ht->handle = handle;
                ht->prio = tp->prio;
+
+               err = u32_replace_hw_hnode(tp, ht, flags);
+               if (err) {
+                       kfree(ht);
+                       return err;
+               }
+
                RCU_INIT_POINTER(ht->next, tp_c->hlist);
                rcu_assign_pointer(tp_c->hlist, ht);
                *arg = (unsigned long)ht;
 
-               u32_replace_hw_hnode(tp, ht, flags);
                return 0;
        }
 
index a63e879..bf8af2c 100644 (file)
@@ -375,6 +375,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                cl->deficit = cl->quantum;
        }
 
+       qdisc_qstats_backlog_inc(sch, skb);
        sch->q.qlen++;
        return err;
 }
@@ -407,6 +408,7 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch)
 
                        bstats_update(&cl->bstats, skb);
                        qdisc_bstats_update(sch, skb);
+                       qdisc_qstats_backlog_dec(sch, skb);
                        sch->q.qlen--;
                        return skb;
                }
@@ -428,6 +430,7 @@ static unsigned int drr_drop(struct Qdisc *sch)
                if (cl->qdisc->ops->drop) {
                        len = cl->qdisc->ops->drop(cl->qdisc);
                        if (len > 0) {
+                               sch->qstats.backlog -= len;
                                sch->q.qlen--;
                                if (cl->qdisc->q.qlen == 0)
                                        list_del(&cl->alist);
@@ -463,6 +466,7 @@ static void drr_reset_qdisc(struct Qdisc *sch)
                        qdisc_reset(cl->qdisc);
                }
        }
+       sch->qstats.backlog = 0;
        sch->q.qlen = 0;
 }
 
index 6883a89..da250b2 100644 (file)
@@ -199,6 +199,7 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        unsigned int idx, prev_backlog, prev_qlen;
        struct fq_codel_flow *flow;
        int uninitialized_var(ret);
+       unsigned int pkt_len;
        bool memory_limited;
 
        idx = fq_codel_classify(skb, sch, &ret);
@@ -230,6 +231,8 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        prev_backlog = sch->qstats.backlog;
        prev_qlen = sch->q.qlen;
 
+       /* save this packet length as it might be dropped by fq_codel_drop() */
+       pkt_len = qdisc_pkt_len(skb);
        /* fq_codel_drop() is quite expensive, as it performs a linear search
         * in q->backlogs[] to find a fat flow.
         * So instead of dropping a single packet, drop half of its backlog
@@ -237,14 +240,23 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
         */
        ret = fq_codel_drop(sch, q->drop_batch_size);
 
-       q->drop_overlimit += prev_qlen - sch->q.qlen;
+       prev_qlen -= sch->q.qlen;
+       prev_backlog -= sch->qstats.backlog;
+       q->drop_overlimit += prev_qlen;
        if (memory_limited)
-               q->drop_overmemory += prev_qlen - sch->q.qlen;
-       /* As we dropped packet(s), better let upper stack know this */
-       qdisc_tree_reduce_backlog(sch, prev_qlen - sch->q.qlen,
-                                 prev_backlog - sch->qstats.backlog);
+               q->drop_overmemory += prev_qlen;
 
-       return ret == idx ? NET_XMIT_CN : NET_XMIT_SUCCESS;
+       /* As we dropped packet(s), better let upper stack know this.
+        * If we dropped a packet for this flow, return NET_XMIT_CN,
+        * but in this case, our parents wont increase their backlogs.
+        */
+       if (ret == idx) {
+               qdisc_tree_reduce_backlog(sch, prev_qlen - 1,
+                                         prev_backlog - pkt_len);
+               return NET_XMIT_CN;
+       }
+       qdisc_tree_reduce_backlog(sch, prev_qlen, prev_backlog);
+       return NET_XMIT_SUCCESS;
 }
 
 /* This is the specific function called from codel_dequeue()
@@ -649,7 +661,7 @@ static int fq_codel_dump_class_stats(struct Qdisc *sch, unsigned long cl,
                qs.backlog = q->backlogs[idx];
                qs.drops = flow->dropped;
        }
-       if (gnet_stats_copy_queue(d, NULL, &qs, 0) < 0)
+       if (gnet_stats_copy_queue(d, NULL, &qs, qs.qlen) < 0)
                return -1;
        if (idx < q->flows_cnt)
                return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
index 269dd71..f9e0e9c 100644 (file)
@@ -49,6 +49,7 @@ static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q)
 {
        q->gso_skb = skb;
        q->qstats.requeues++;
+       qdisc_qstats_backlog_inc(q, skb);
        q->q.qlen++;    /* it's still part of the queue */
        __netif_schedule(q);
 
@@ -92,6 +93,7 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate,
                txq = skb_get_tx_queue(txq->dev, skb);
                if (!netif_xmit_frozen_or_stopped(txq)) {
                        q->gso_skb = NULL;
+                       qdisc_qstats_backlog_dec(q, skb);
                        q->q.qlen--;
                } else
                        skb = NULL;
index d783d7c..1ac9f9f 100644 (file)
@@ -1529,6 +1529,7 @@ hfsc_reset_qdisc(struct Qdisc *sch)
        q->eligible = RB_ROOT;
        INIT_LIST_HEAD(&q->droplist);
        qdisc_watchdog_cancel(&q->watchdog);
+       sch->qstats.backlog = 0;
        sch->q.qlen = 0;
 }
 
@@ -1559,14 +1560,6 @@ hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
        struct hfsc_sched *q = qdisc_priv(sch);
        unsigned char *b = skb_tail_pointer(skb);
        struct tc_hfsc_qopt qopt;
-       struct hfsc_class *cl;
-       unsigned int i;
-
-       sch->qstats.backlog = 0;
-       for (i = 0; i < q->clhash.hashsize; i++) {
-               hlist_for_each_entry(cl, &q->clhash.hash[i], cl_common.hnode)
-                       sch->qstats.backlog += cl->qdisc->qstats.backlog;
-       }
 
        qopt.defcls = q->defcls;
        if (nla_put(skb, TCA_OPTIONS, sizeof(qopt), &qopt))
@@ -1604,6 +1597,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        if (cl->qdisc->q.qlen == 1)
                set_active(cl, qdisc_pkt_len(skb));
 
+       qdisc_qstats_backlog_inc(sch, skb);
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
@@ -1672,6 +1666,7 @@ hfsc_dequeue(struct Qdisc *sch)
 
        qdisc_unthrottled(sch);
        qdisc_bstats_update(sch, skb);
+       qdisc_qstats_backlog_dec(sch, skb);
        sch->q.qlen--;
 
        return skb;
@@ -1695,6 +1690,7 @@ hfsc_drop(struct Qdisc *sch)
                        }
                        cl->qstats.drops++;
                        qdisc_qstats_drop(sch);
+                       sch->qstats.backlog -= len;
                        sch->q.qlen--;
                        return len;
                }
index 10adbc6..8fe6999 100644 (file)
@@ -27,6 +27,11 @@ static unsigned long ingress_get(struct Qdisc *sch, u32 classid)
        return TC_H_MIN(classid) + 1;
 }
 
+static bool ingress_cl_offload(u32 classid)
+{
+       return true;
+}
+
 static unsigned long ingress_bind_filter(struct Qdisc *sch,
                                         unsigned long parent, u32 classid)
 {
@@ -86,6 +91,7 @@ static const struct Qdisc_class_ops ingress_class_ops = {
        .put            =       ingress_put,
        .walk           =       ingress_walk,
        .tcf_chain      =       ingress_find_tcf,
+       .tcf_cl_offload =       ingress_cl_offload,
        .bind_tcf       =       ingress_bind_filter,
        .unbind_tcf     =       ingress_put,
 };
@@ -110,6 +116,11 @@ static unsigned long clsact_get(struct Qdisc *sch, u32 classid)
        }
 }
 
+static bool clsact_cl_offload(u32 classid)
+{
+       return TC_H_MIN(classid) == TC_H_MIN(TC_H_MIN_INGRESS);
+}
+
 static unsigned long clsact_bind_filter(struct Qdisc *sch,
                                        unsigned long parent, u32 classid)
 {
@@ -158,6 +169,7 @@ static const struct Qdisc_class_ops clsact_class_ops = {
        .put            =       ingress_put,
        .walk           =       ingress_walk,
        .tcf_chain      =       clsact_find_tcf,
+       .tcf_cl_offload =       clsact_cl_offload,
        .bind_tcf       =       clsact_bind_filter,
        .unbind_tcf     =       ingress_put,
 };
index fee1b15..4b0a821 100644 (file)
@@ -85,6 +85,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
        ret = qdisc_enqueue(skb, qdisc);
        if (ret == NET_XMIT_SUCCESS) {
+               qdisc_qstats_backlog_inc(sch, skb);
                sch->q.qlen++;
                return NET_XMIT_SUCCESS;
        }
@@ -117,6 +118,7 @@ static struct sk_buff *prio_dequeue(struct Qdisc *sch)
                struct sk_buff *skb = qdisc_dequeue_peeked(qdisc);
                if (skb) {
                        qdisc_bstats_update(sch, skb);
+                       qdisc_qstats_backlog_dec(sch, skb);
                        sch->q.qlen--;
                        return skb;
                }
@@ -135,6 +137,7 @@ static unsigned int prio_drop(struct Qdisc *sch)
        for (prio = q->bands-1; prio >= 0; prio--) {
                qdisc = q->queues[prio];
                if (qdisc->ops->drop && (len = qdisc->ops->drop(qdisc)) != 0) {
+                       sch->qstats.backlog -= len;
                        sch->q.qlen--;
                        return len;
                }
@@ -151,6 +154,7 @@ prio_reset(struct Qdisc *sch)
 
        for (prio = 0; prio < q->bands; prio++)
                qdisc_reset(q->queues[prio]);
+       sch->qstats.backlog = 0;
        sch->q.qlen = 0;
 }
 
index 8d2d8d9..f18857f 100644 (file)
@@ -1235,8 +1235,10 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                         cl->agg->lmax, qdisc_pkt_len(skb), cl->common.classid);
                err = qfq_change_agg(sch, cl, cl->agg->class_weight,
                                     qdisc_pkt_len(skb));
-               if (err)
-                       return err;
+               if (err) {
+                       cl->qstats.drops++;
+                       return qdisc_drop(skb, sch);
+               }
        }
 
        err = qdisc_enqueue(skb, cl->qdisc);
index 8c0508c..91578bd 100644 (file)
@@ -97,6 +97,7 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
        ret = qdisc_enqueue(skb, child);
        if (likely(ret == NET_XMIT_SUCCESS)) {
+               qdisc_qstats_backlog_inc(sch, skb);
                sch->q.qlen++;
        } else if (net_xmit_drop_count(ret)) {
                q->stats.pdrop++;
@@ -118,6 +119,7 @@ static struct sk_buff *red_dequeue(struct Qdisc *sch)
        skb = child->dequeue(child);
        if (skb) {
                qdisc_bstats_update(sch, skb);
+               qdisc_qstats_backlog_dec(sch, skb);
                sch->q.qlen--;
        } else {
                if (!red_is_idling(&q->vars))
@@ -143,6 +145,7 @@ static unsigned int red_drop(struct Qdisc *sch)
        if (child->ops->drop && (len = child->ops->drop(child)) > 0) {
                q->stats.other++;
                qdisc_qstats_drop(sch);
+               sch->qstats.backlog -= len;
                sch->q.qlen--;
                return len;
        }
@@ -158,6 +161,7 @@ static void red_reset(struct Qdisc *sch)
        struct red_sched_data *q = qdisc_priv(sch);
 
        qdisc_reset(q->qdisc);
+       sch->qstats.backlog = 0;
        sch->q.qlen = 0;
        red_restart(&q->vars);
 }
index 83b90b5..3161e49 100644 (file)
@@ -207,6 +207,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                return ret;
        }
 
+       qdisc_qstats_backlog_inc(sch, skb);
        sch->q.qlen++;
        return NET_XMIT_SUCCESS;
 }
@@ -217,6 +218,7 @@ static unsigned int tbf_drop(struct Qdisc *sch)
        unsigned int len = 0;
 
        if (q->qdisc->ops->drop && (len = q->qdisc->ops->drop(q->qdisc)) != 0) {
+               sch->qstats.backlog -= len;
                sch->q.qlen--;
                qdisc_qstats_drop(sch);
        }
@@ -263,6 +265,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc *sch)
                        q->t_c = now;
                        q->tokens = toks;
                        q->ptokens = ptoks;
+                       qdisc_qstats_backlog_dec(sch, skb);
                        sch->q.qlen--;
                        qdisc_unthrottled(sch);
                        qdisc_bstats_update(sch, skb);
@@ -294,6 +297,7 @@ static void tbf_reset(struct Qdisc *sch)
        struct tbf_sched_data *q = qdisc_priv(sch);
 
        qdisc_reset(q->qdisc);
+       sch->qstats.backlog = 0;
        sch->q.qlen = 0;
        q->t_c = ktime_get_ns();
        q->tokens = q->buffer;
index f795b1d..3ad9fab 100644 (file)
@@ -604,7 +604,8 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg,
 
        link_info.dest = nla_get_flag(link[TIPC_NLA_LINK_DEST]);
        link_info.up = htonl(nla_get_flag(link[TIPC_NLA_LINK_UP]));
-       strcpy(link_info.str, nla_data(link[TIPC_NLA_LINK_NAME]));
+       nla_strlcpy(link_info.str, nla_data(link[TIPC_NLA_LINK_NAME]),
+                   TIPC_MAX_LINK_NAME);
 
        return tipc_add_tlv(msg->rep, TIPC_TLV_LINK_INFO,
                            &link_info, sizeof(link_info));
index d25c82b..ecca389 100644 (file)
@@ -363,8 +363,6 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
        WARN_ON(ops->remain_on_channel && !ops->cancel_remain_on_channel);
        WARN_ON(ops->tdls_channel_switch && !ops->tdls_cancel_channel_switch);
        WARN_ON(ops->add_tx_ts && !ops->del_tx_ts);
-       WARN_ON(ops->set_tx_power && !ops->get_tx_power);
-       WARN_ON(ops->set_antenna && !ops->get_antenna);
 
        alloc_size = sizeof(*rdev) + sizeof_priv;
 
index 6250b1c..dbb2738 100644 (file)
@@ -958,8 +958,29 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr,
                        return private(dev, iwr, cmd, info, handler);
        }
        /* Old driver API : call driver ioctl handler */
-       if (dev->netdev_ops->ndo_do_ioctl)
-               return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
+       if (dev->netdev_ops->ndo_do_ioctl) {
+#ifdef CONFIG_COMPAT
+               if (info->flags & IW_REQUEST_FLAG_COMPAT) {
+                       int ret = 0;
+                       struct iwreq iwr_lcl;
+                       struct compat_iw_point *iwp_compat = (void *) &iwr->u.data;
+
+                       memcpy(&iwr_lcl, iwr, sizeof(struct iwreq));
+                       iwr_lcl.u.data.pointer = compat_ptr(iwp_compat->pointer);
+                       iwr_lcl.u.data.length = iwp_compat->length;
+                       iwr_lcl.u.data.flags = iwp_compat->flags;
+
+                       ret = dev->netdev_ops->ndo_do_ioctl(dev, (void *) &iwr_lcl, cmd);
+
+                       iwp_compat->pointer = ptr_to_compat(iwr_lcl.u.data.pointer);
+                       iwp_compat->length = iwr_lcl.u.data.length;
+                       iwp_compat->flags = iwr_lcl.u.data.flags;
+
+                       return ret;
+               } else
+#endif
+                       return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
+       }
        return -EOPNOTSUPP;
 }
 
index 9a0d144..94089fc 100644 (file)
@@ -365,8 +365,11 @@ enum {
 
 #define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
 #define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
+#define IS_KBL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa171)
+#define IS_KBL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d71)
 #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
-#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
+#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) || \
+                       IS_KBL(pci) || IS_KBL_LP(pci)
 
 static char *driver_short_names[] = {
        [AZX_DRIVER_ICH] = "HDA Intel",
@@ -2181,6 +2184,12 @@ static const struct pci_device_id azx_ids[] = {
        /* Sunrise Point-LP */
        { PCI_DEVICE(0x8086, 0x9d70),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+       /* Kabylake */
+       { PCI_DEVICE(0x8086, 0xa171),
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+       /* Kabylake-LP */
+       { PCI_DEVICE(0x8086, 0x9d71),
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
        /* Broxton-P(Apollolake) */
        { PCI_DEVICE(0x8086, 0x5a98),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON },
index d53c25e..0fe18ed 100644 (file)
@@ -346,6 +346,9 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
        case 0x10ec0234:
        case 0x10ec0274:
        case 0x10ec0294:
+       case 0x10ec0700:
+       case 0x10ec0701:
+       case 0x10ec0703:
                alc_update_coef_idx(codec, 0x10, 1<<15, 0);
                break;
        case 0x10ec0662:
@@ -2655,6 +2658,7 @@ enum {
        ALC269_TYPE_ALC256,
        ALC269_TYPE_ALC225,
        ALC269_TYPE_ALC294,
+       ALC269_TYPE_ALC700,
 };
 
 /*
@@ -2686,6 +2690,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        case ALC269_TYPE_ALC256:
        case ALC269_TYPE_ALC225:
        case ALC269_TYPE_ALC294:
+       case ALC269_TYPE_ALC700:
                ssids = alc269_ssids;
                break;
        default:
@@ -3618,13 +3623,20 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
 static void alc_headset_mode_unplugged(struct hda_codec *codec)
 {
        static struct coef_fw coef0255[] = {
-               WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
                WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
                UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
                WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
                WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */
                {}
        };
+       static struct coef_fw coef0255_1[] = {
+               WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
+               {}
+       };
+       static struct coef_fw coef0256[] = {
+               WRITE_COEF(0x1b, 0x0c4b), /* LDO and MISC control */
+               {}
+       };
        static struct coef_fw coef0233[] = {
                WRITE_COEF(0x1b, 0x0c0b),
                WRITE_COEF(0x45, 0xc429),
@@ -3677,7 +3689,11 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
 
        switch (codec->core.vendor_id) {
        case 0x10ec0255:
+               alc_process_coef_fw(codec, coef0255_1);
+               alc_process_coef_fw(codec, coef0255);
+               break;
        case 0x10ec0256:
+               alc_process_coef_fw(codec, coef0256);
                alc_process_coef_fw(codec, coef0255);
                break;
        case 0x10ec0233:
@@ -3896,6 +3912,12 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
                WRITE_COEFEX(0x57, 0x03, 0x8ea6),
                {}
        };
+       static struct coef_fw coef0256[] = {
+               WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
+               WRITE_COEF(0x1b, 0x0c6b),
+               WRITE_COEFEX(0x57, 0x03, 0x8ea6),
+               {}
+       };
        static struct coef_fw coef0233[] = {
                WRITE_COEF(0x45, 0xd429),
                WRITE_COEF(0x1b, 0x0c2b),
@@ -3936,9 +3958,11 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
 
        switch (codec->core.vendor_id) {
        case 0x10ec0255:
-       case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
                break;
+       case 0x10ec0256:
+               alc_process_coef_fw(codec, coef0256);
+               break;
        case 0x10ec0233:
        case 0x10ec0283:
                alc_process_coef_fw(codec, coef0233);
@@ -3978,6 +4002,12 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
                WRITE_COEFEX(0x57, 0x03, 0x8ea6),
                {}
        };
+       static struct coef_fw coef0256[] = {
+               WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
+               WRITE_COEF(0x1b, 0x0c6b),
+               WRITE_COEFEX(0x57, 0x03, 0x8ea6),
+               {}
+       };
        static struct coef_fw coef0233[] = {
                WRITE_COEF(0x45, 0xe429),
                WRITE_COEF(0x1b, 0x0c2b),
@@ -4018,9 +4048,11 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
 
        switch (codec->core.vendor_id) {
        case 0x10ec0255:
-       case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
                break;
+       case 0x10ec0256:
+               alc_process_coef_fw(codec, coef0256);
+               break;
        case 0x10ec0233:
        case 0x10ec0283:
                alc_process_coef_fw(codec, coef0233);
@@ -4266,7 +4298,7 @@ static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
 static void alc255_set_default_jack_type(struct hda_codec *codec)
 {
        /* Set to iphone type */
-       static struct coef_fw fw[] = {
+       static struct coef_fw alc255fw[] = {
                WRITE_COEF(0x1b, 0x880b),
                WRITE_COEF(0x45, 0xd089),
                WRITE_COEF(0x1b, 0x080b),
@@ -4274,7 +4306,22 @@ static void alc255_set_default_jack_type(struct hda_codec *codec)
                WRITE_COEF(0x1b, 0x0c0b),
                {}
        };
-       alc_process_coef_fw(codec, fw);
+       static struct coef_fw alc256fw[] = {
+               WRITE_COEF(0x1b, 0x884b),
+               WRITE_COEF(0x45, 0xd089),
+               WRITE_COEF(0x1b, 0x084b),
+               WRITE_COEF(0x46, 0x0004),
+               WRITE_COEF(0x1b, 0x0c4b),
+               {}
+       };
+       switch (codec->core.vendor_id) {
+       case 0x10ec0255:
+               alc_process_coef_fw(codec, alc255fw);
+               break;
+       case 0x10ec0256:
+               alc_process_coef_fw(codec, alc256fw);
+               break;
+       }
        msleep(30);
 }
 
@@ -5587,6 +5634,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x2218, "Thinkpad X1 Carbon 2nd", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
+       SND_PCI_QUIRK(0x17aa, 0x2231, "Thinkpad T560", ALC292_FIXUP_TPT460),
        SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460),
        SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
@@ -5775,6 +5823,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x12, 0x90a60180},
                {0x14, 0x90170130},
                {0x21, 0x02211040}),
+       SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5565", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+               {0x12, 0x90a60180},
+               {0x14, 0x90170120},
+               {0x21, 0x02211030}),
        SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
                {0x12, 0x90a60160},
                {0x14, 0x90170120},
@@ -6053,6 +6105,14 @@ static int patch_alc269(struct hda_codec *codec)
        case 0x10ec0294:
                spec->codec_variant = ALC269_TYPE_ALC294;
                break;
+       case 0x10ec0700:
+       case 0x10ec0701:
+       case 0x10ec0703:
+               spec->codec_variant = ALC269_TYPE_ALC700;
+               spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
+               alc_update_coef_idx(codec, 0x4a, 0, 1 << 15); /* Combo jack auto trigger control */
+               break;
+
        }
 
        if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
@@ -7008,6 +7068,9 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0670, "ALC670", patch_alc662),
        HDA_CODEC_ENTRY(0x10ec0671, "ALC671", patch_alc662),
        HDA_CODEC_ENTRY(0x10ec0680, "ALC680", patch_alc680),
+       HDA_CODEC_ENTRY(0x10ec0700, "ALC700", patch_alc269),
+       HDA_CODEC_ENTRY(0x10ec0701, "ALC701", patch_alc269),
+       HDA_CODEC_ENTRY(0x10ec0703, "ALC703", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0867, "ALC891", patch_alc882),
        HDA_CODEC_ENTRY(0x10ec0880, "ALC880", patch_alc880),
        HDA_CODEC_ENTRY(0x10ec0882, "ALC882", patch_alc882),
index 96ba386..4a82174 100644 (file)
@@ -111,9 +111,9 @@ static void attach_ebpf(int fd, uint16_t mod)
        memset(&attr, 0, sizeof(attr));
        attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
        attr.insn_cnt = ARRAY_SIZE(prog);
-       attr.insns = (uint64_t)prog;
-       attr.license = (uint64_t)bpf_license;
-       attr.log_buf = (uint64_t)bpf_log_buf;
+       attr.insns = (unsigned long) &prog;
+       attr.license = (unsigned long) &bpf_license;
+       attr.log_buf = (unsigned long) &bpf_log_buf;
        attr.log_size = sizeof(bpf_log_buf);
        attr.log_level = 1;
        attr.kern_version = 0;
@@ -351,8 +351,8 @@ static void test_filter_no_reuseport(const struct test_params p)
        memset(&eprog, 0, sizeof(eprog));
        eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
        eprog.insn_cnt = ARRAY_SIZE(ecode);
-       eprog.insns = (uint64_t)ecode;
-       eprog.license = (uint64_t)bpf_license;
+       eprog.insns = (unsigned long) &ecode;
+       eprog.license = (unsigned long) &bpf_license;
        eprog.kern_version = 0;
 
        memset(&cprog, 0, sizeof(cprog));