Merge git://git.kernel.org:/pub/scm/linux/kernel/git/netdev/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 10 Mar 2021 01:15:56 +0000 (17:15 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 10 Mar 2021 01:15:56 +0000 (17:15 -0800)
Pull networking fixes from David Miller:

 1) Fix transmissions in dynamic SMPS mode in ath9k, from Felix Fietkau.

 2) TX skb error handling fix in mt76 driver, also from Felix.

 3) Fix BPF_FETCH atomic in x86 JIT, from Brendan Jackman.

 4) Avoid double free of percpu pointers when freeing a cloned bpf prog.
    From Cong Wang.

 5) Use correct printf format for dma_addr_t in ath11k, from Geert
    Uytterhoeven.

 6) Fix resolve_btfids build with older toolchains, from Kun-Chuan
    Hsieh.

 7) Don't report truncated frames to mac80211 in mt76 driver, from
    Lorenzop Bianconi.

 8) Fix watcdog timeout on suspend/resume of stmmac, from Joakim Zhang.

 9) mscc ocelot needs NET_DEVLINK selct in Kconfig, from Arnd Bergmann.

10) Fix sign comparison bug in TCP_ZEROCOPY_RECEIVE getsockopt(), from
    Arjun Roy.

11) Ignore routes with deleted nexthop object in mlxsw, from Ido
    Schimmel.

12) Need to undo tcp early demux lookup sometimes in nf_nat, from
    Florian Westphal.

13) Fix gro aggregation for udp encaps with zero csum, from Daniel
    Borkmann.

14) Make sure to always use imp*_ndo_send when necessaey, from Jason A.
    Donenfeld.

15) Fix TRSCER masks in sh_eth driver from Sergey Shtylyov.

16) prevent overly huge skb allocationsd in qrtr, from Pavel Skripkin.

17) Prevent rx ring copnsumer index loss of sync in enetc, from Vladimir
    Oltean.

18) Make sure textsearch copntrol block is large enough, from Wilem de
    Bruijn.

19) Revert MAC changes to r8152 leading to instability, from Hates Wang.

20) Advance iov in 9p even for empty reads, from Jissheng Zhang.

21) Double hook unregister in nftables, from PabloNeira Ayuso.

22) Fix memleak in ixgbe, fropm Dinghao Liu.

23) Avoid dups in pkt scheduler class dumps, from Maximilian Heyne.

24) Various mptcp fixes from Florian Westphal, Paolo Abeni, and Geliang
    Tang.

25) Fix DOI refcount bugs in cipso, from Paul Moore.

26) One too many irqsave in ibmvnic, from Junlin Yang.

27) Fix infinite loop with MPLS gso segmenting via virtio_net, from
    Balazs Nemeth.

* git://git.kernel.org:/pub/scm/linux/kernel/git/netdev/net: (164 commits)
  s390/qeth: fix notification for pending buffers during teardown
  s390/qeth: schedule TX NAPI on QAOB completion
  s390/qeth: improve completion of pending TX buffers
  s390/qeth: fix memory leak after failed TX Buffer allocation
  net: avoid infinite loop in mpls_gso_segment when mpls_hlen == 0
  net: check if protocol extracted by virtio_net_hdr_set_proto is correct
  net: dsa: xrs700x: check if partner is same as port in hsr join
  net: lapbether: Remove netif_start_queue / netif_stop_queue
  atm: idt77252: fix null-ptr-dereference
  atm: uPD98402: fix incorrect allocation
  atm: fix a typo in the struct description
  net: qrtr: fix error return code of qrtr_sendmsg()
  mptcp: fix length of ADD_ADDR with port sub-option
  net: bonding: fix error return code of bond_neigh_init()
  net: enetc: allow hardware timestamping on TX queues with tc-etf enabled
  net: enetc: set MAC RX FIFO to recommended value
  net: davicom: Use platform_get_irq_optional()
  net: davicom: Fix regulator not turned off on driver removal
  net: davicom: Fix regulator not turned off on failed probe
  net: dsa: fix switchdev objects on bridge master mistakenly being applied on ports
  ...

159 files changed:
Documentation/networking/bonding.rst
Documentation/networking/netdev-FAQ.rst
Documentation/process/stable-kernel-rules.rst
Documentation/process/submitting-patches.rst
MAINTAINERS
arch/x86/net/bpf_jit_comp.c
drivers/atm/eni.c
drivers/atm/idt77105.c
drivers/atm/lanai.c
drivers/atm/uPD98402.c
drivers/net/bonding/bond_main.c
drivers/net/can/flexcan.c
drivers/net/can/m_can/tcan4x5x-core.c
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/mt7530.c
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/dsa/xrs700x/xrs700x.c
drivers/net/ethernet/atheros/alx/main.c
drivers/net/ethernet/broadcom/bcm4908_enet.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/freescale/enetc/enetc.c
drivers/net/ethernet/freescale/enetc/enetc.h
drivers/net/ethernet/freescale/enetc/enetc_hw.h
drivers/net/ethernet/freescale/enetc/enetc_pf.c
drivers/net/ethernet/freescale/enetc/enetc_vf.c
drivers/net/ethernet/freescale/fec_ptp.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/hisilicon/hns/hns_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbevf/ipsec.c
drivers/net/ethernet/marvell/octeontx2/af/cgx.c
drivers/net/ethernet/mediatek/mtk_star_emac.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlxsw/reg.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/switchx2.c
drivers/net/ethernet/microchip/lan743x_main.c
drivers/net/ethernet/mscc/Kconfig
drivers/net/ethernet/mscc/ocelot_flower.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
drivers/net/ethernet/stmicro/stmmac/enh_desc.c
drivers/net/ethernet/stmicro/stmmac/hwif.h
drivers/net/ethernet/stmicro/stmmac/norm_desc.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/sun/niu.c
drivers/net/ethernet/tehuti/tehuti.c
drivers/net/hamradio/6pack.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c
drivers/net/netdevsim/netdev.c
drivers/net/phy/dp83822.c
drivers/net/phy/dp83tc811.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/usb/usbnet.c
drivers/net/wan/fsl_ucc_hdlc.c
drivers/net/wan/lapbether.c
drivers/net/wireless/ath/ath11k/mac.c
drivers/net/wireless/ath/ath11k/qmi.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/intel/iwlwifi/pcie/rx.c
drivers/net/wireless/mediatek/mt76/dma.c
drivers/net/wireless/mediatek/mt76/mt7915/mac.c
drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
drivers/net/xen-netback/netback.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
include/linux/atmdev.h
include/linux/can/skb.h
include/linux/netdevice.h
include/linux/textsearch.h
include/linux/virtio_net.h
include/uapi/linux/bpf.h
include/uapi/linux/l2tp.h
include/uapi/linux/netfilter/nfnetlink_cthelper.h
kernel/bpf/btf.c
kernel/bpf/core.c
kernel/bpf/verifier.c
net/9p/client.c
net/core/rtnetlink.c
net/core/skbuff.c
net/dsa/Kconfig
net/dsa/dsa_priv.h
net/dsa/slave.c
net/dsa/tag_mtk.c
net/dsa/tag_rtl4_a.c
net/ethtool/channels.c
net/ipv4/cipso_ipv4.c
net/ipv4/inetpeer.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_vti.c
net/ipv4/nexthop.c
net/ipv4/tcp.c
net/ipv4/udp_offload.c
net/ipv6/calipso.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/sit.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_netlink.c
net/mpls/mpls_gso.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_nat_proto.c
net/netfilter/nf_tables_api.c
net/netfilter/x_tables.c
net/netlabel/netlabel_cipso_v4.c
net/qrtr/qrtr.c
net/sched/sch_api.c
net/sctp/tsnmap.c
samples/bpf/xdpsock_user.c
tools/bpf/resolve_btfids/main.c
tools/include/uapi/linux/bpf.h
tools/lib/bpf/xsk.c
tools/testing/selftests/bpf/progs/netif_receive_skb.c
tools/testing/selftests/bpf/progs/test_global_func11.c
tools/testing/selftests/bpf/progs/test_tunnel_kern.c
tools/testing/selftests/bpf/verifier/array_access.c
tools/testing/selftests/bpf/verifier/atomic_and.c
tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c
tools/testing/selftests/bpf/verifier/atomic_or.c
tools/testing/selftests/net/fib_nexthops.sh
tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d_vlan.sh
tools/testing/selftests/net/ipsec.c
tools/testing/selftests/netfilter/Makefile
tools/testing/selftests/netfilter/nf_nat_edemux.sh [new file with mode: 0755]

index 5f690f0..62f2aab 100644 (file)
@@ -1988,7 +1988,7 @@ netif_carrier.
 If use_carrier is 0, then the MII monitor will first query the
 device's (via ioctl) MII registers and check the link state.  If that
 request fails (not just that it returns carrier down), then the MII
-monitor will make an ethtool ETHOOL_GLINK request to attempt to obtain
+monitor will make an ethtool ETHTOOL_GLINK request to attempt to obtain
 the same information.  If both methods fail (i.e., the driver either
 does not support or had some error in processing both the MII register
 and ethtool requests), then the MII monitor will assume the link is
index a64c01b..91b2cf7 100644 (file)
@@ -142,73 +142,13 @@ Please send incremental versions on top of what has been merged in order to fix
 the patches the way they would look like if your latest patch series was to be
 merged.
 
-How can I tell what patches are queued up for backporting to the various stable releases?
------------------------------------------------------------------------------------------
-Normally Greg Kroah-Hartman collects stable commits himself, but for
-networking, Dave collects up patches he deems critical for the
-networking subsystem, and then hands them off to Greg.
-
-There is a patchworks queue that you can see here:
-
-  https://patchwork.kernel.org/bundle/netdev/stable/?state=*
-
-It contains the patches which Dave has selected, but not yet handed off
-to Greg.  If Greg already has the patch, then it will be here:
-
-  https://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git
-
-A quick way to find whether the patch is in this stable-queue is to
-simply clone the repo, and then git grep the mainline commit ID, e.g.
-::
-
-  stable-queue$ git grep -l 284041ef21fdf2e
-  releases/3.0.84/ipv6-fix-possible-crashes-in-ip6_cork_release.patch
-  releases/3.4.51/ipv6-fix-possible-crashes-in-ip6_cork_release.patch
-  releases/3.9.8/ipv6-fix-possible-crashes-in-ip6_cork_release.patch
-  stable/stable-queue$
-
-I see a network patch and I think it should be backported to stable. Should I request it via stable@vger.kernel.org like the references in the kernel's Documentation/process/stable-kernel-rules.rst file say?
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-No, not for networking.  Check the stable queues as per above first
-to see if it is already queued.  If not, then send a mail to netdev,
-listing the upstream commit ID and why you think it should be a stable
-candidate.
-
-Before you jump to go do the above, do note that the normal stable rules
-in :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
-still apply.  So you need to explicitly indicate why it is a critical
-fix and exactly what users are impacted.  In addition, you need to
-convince yourself that you *really* think it has been overlooked,
-vs. having been considered and rejected.
-
-Generally speaking, the longer it has had a chance to "soak" in
-mainline, the better the odds that it is an OK candidate for stable.  So
-scrambling to request a commit be added the day after it appears should
-be avoided.
-
-I have created a network patch and I think it should be backported to stable. Should I add a Cc: stable@vger.kernel.org like the references in the kernel's Documentation/ directory say?
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-No.  See above answer.  In short, if you think it really belongs in
-stable, then ensure you write a decent commit log that describes who
-gets impacted by the bug fix and how it manifests itself, and when the
-bug was introduced.  If you do that properly, then the commit will get
-handled appropriately and most likely get put in the patchworks stable
-queue if it really warrants it.
-
-If you think there is some valid information relating to it being in
-stable that does *not* belong in the commit log, then use the three dash
-marker line as described in
-:ref:`Documentation/process/submitting-patches.rst <the_canonical_patch_format>`
-to temporarily embed that information into the patch that you send.
-
-Are all networking bug fixes backported to all stable releases?
+Are there special rules regarding stable submissions on netdev?
 ---------------------------------------------------------------
-Due to capacity, Dave could only take care of the backports for the
-last two stable releases. For earlier stable releases, each stable
-branch maintainer is supposed to take care of them. If you find any
-patch is missing from an earlier stable branch, please notify
-stable@vger.kernel.org with either a commit ID or a formal patch
-backported, and CC Dave and other relevant networking developers.
+While it used to be the case that netdev submissions were not supposed
+to carry explicit ``CC: stable@vger.kernel.org`` tags that is no longer
+the case today. Please follow the standard stable rules in
+:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`,
+and make sure you include appropriate Fixes tags!
 
 Is the comment style convention different for the networking content?
 ---------------------------------------------------------------------
index 3973556..003c865 100644 (file)
@@ -35,12 +35,6 @@ Rules on what kind of patches are accepted, and which ones are not, into the
 Procedure for submitting patches to the -stable tree
 ----------------------------------------------------
 
- - If the patch covers files in net/ or drivers/net please follow netdev stable
-   submission guidelines as described in
-   :ref:`Documentation/networking/netdev-FAQ.rst <netdev-FAQ>`
-   after first checking the stable networking queue at
-   https://patchwork.kernel.org/bundle/netdev/stable/?state=*
-   to ensure the requested patch is not already queued up.
  - Security patches should not be handled (solely) by the -stable review
    process but should follow the procedures in
    :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`.
index 8c991c8..91de63b 100644 (file)
@@ -250,11 +250,6 @@ should also read
 :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
 in addition to this file.
 
-Note, however, that some subsystem maintainers want to come to their own
-conclusions on which patches should go to the stable trees.  The networking
-maintainer, in particular, would rather not see individual developers
-adding lines like the above to their patches.
-
 If changes affect userland-kernel interfaces, please send the MAN-PAGES
 maintainer (as listed in the MAINTAINERS file) a man-pages patch, or at
 least a notification of the change, so that some information makes its way
index d92f85c..f2e34ed 100644 (file)
@@ -10716,7 +10716,8 @@ F:      drivers/net/ethernet/marvell/mvpp2/
 
 MARVELL MWIFIEX WIRELESS DRIVER
 M:     Amitkumar Karwar <amitkarwar@gmail.com>
-M:     Ganapathi Bhat <ganapathi.bhat@nxp.com>
+M:     Ganapathi Bhat <ganapathi017@gmail.com>
+M:     Sharvari Harisangam <sharvari.harisangam@nxp.com>
 M:     Xinming Hu <huxinming820@gmail.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
index 79e7a0e..6926d0c 100644 (file)
@@ -1349,6 +1349,7 @@ st:                       if (is_imm8(insn->off))
                            insn->imm == (BPF_XOR | BPF_FETCH)) {
                                u8 *branch_target;
                                bool is64 = BPF_SIZE(insn->code) == BPF_DW;
+                               u32 real_src_reg = src_reg;
 
                                /*
                                 * Can't be implemented with a single x86 insn.
@@ -1357,6 +1358,9 @@ st:                       if (is_imm8(insn->off))
 
                                /* Will need RAX as a CMPXCHG operand so save R0 */
                                emit_mov_reg(&prog, true, BPF_REG_AX, BPF_REG_0);
+                               if (src_reg == BPF_REG_0)
+                                       real_src_reg = BPF_REG_AX;
+
                                branch_target = prog;
                                /* Load old value */
                                emit_ldx(&prog, BPF_SIZE(insn->code),
@@ -1366,9 +1370,9 @@ st:                       if (is_imm8(insn->off))
                                 * put the result in the AUX_REG.
                                 */
                                emit_mov_reg(&prog, is64, AUX_REG, BPF_REG_0);
-                               maybe_emit_mod(&prog, AUX_REG, src_reg, is64);
+                               maybe_emit_mod(&prog, AUX_REG, real_src_reg, is64);
                                EMIT2(simple_alu_opcodes[BPF_OP(insn->imm)],
-                                     add_2reg(0xC0, AUX_REG, src_reg));
+                                     add_2reg(0xC0, AUX_REG, real_src_reg));
                                /* Attempt to swap in new value */
                                err = emit_atomic(&prog, BPF_CMPXCHG,
                                                  dst_reg, AUX_REG, insn->off,
@@ -1381,7 +1385,7 @@ st:                       if (is_imm8(insn->off))
                                 */
                                EMIT2(X86_JNE, -(prog - branch_target) - 2);
                                /* Return the pre-modification value */
-                               emit_mov_reg(&prog, is64, src_reg, BPF_REG_0);
+                               emit_mov_reg(&prog, is64, real_src_reg, BPF_REG_0);
                                /* Restore R0 after clobbering RAX */
                                emit_mov_reg(&prog, true, BPF_REG_0, BPF_REG_AX);
                                break;
index 316a994..b574cce 100644 (file)
@@ -2260,7 +2260,8 @@ out:
        return rc;
 
 err_eni_release:
-       eni_do_release(dev);
+       dev->phy = NULL;
+       iounmap(ENI_DEV(dev)->ioaddr);
 err_unregister:
        atm_dev_deregister(dev);
 err_free_consistent:
index 3c081b6..bfca7b8 100644 (file)
@@ -262,7 +262,7 @@ static int idt77105_start(struct atm_dev *dev)
 {
        unsigned long flags;
 
-       if (!(dev->dev_data = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL)))
+       if (!(dev->phy_data = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL)))
                return -ENOMEM;
        PRIV(dev)->dev = dev;
        spin_lock_irqsave(&idt77105_priv_lock, flags);
@@ -337,7 +337,7 @@ static int idt77105_stop(struct atm_dev *dev)
                 else
                     idt77105_all = walk->next;
                dev->phy = NULL;
-                dev->dev_data = NULL;
+                dev->phy_data = NULL;
                 kfree(walk);
                 break;
             }
index d7277c2..32d7aa1 100644 (file)
@@ -2233,6 +2233,7 @@ static int lanai_dev_open(struct atm_dev *atmdev)
        conf1_write(lanai);
 #endif
        iounmap(lanai->base);
+       lanai->base = NULL;
     error_pci:
        pci_disable_device(lanai->pci);
     error:
@@ -2245,6 +2246,8 @@ static int lanai_dev_open(struct atm_dev *atmdev)
 static void lanai_dev_close(struct atm_dev *atmdev)
 {
        struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data;
+       if (lanai->base==NULL)
+               return;
        printk(KERN_INFO DEV_LABEL "(itf %d): shutting down interface\n",
            lanai->number);
        lanai_timed_poll_stop(lanai);
@@ -2552,7 +2555,7 @@ static int lanai_init_one(struct pci_dev *pci,
        struct atm_dev *atmdev;
        int result;
 
-       lanai = kmalloc(sizeof(*lanai), GFP_KERNEL);
+       lanai = kzalloc(sizeof(*lanai), GFP_KERNEL);
        if (lanai == NULL) {
                printk(KERN_ERR DEV_LABEL
                       ": couldn't allocate dev_data structure!\n");
index 7850758..239852d 100644 (file)
@@ -211,7 +211,7 @@ static void uPD98402_int(struct atm_dev *dev)
 static int uPD98402_start(struct atm_dev *dev)
 {
        DPRINTK("phy_start\n");
-       if (!(dev->dev_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL)))
+       if (!(dev->phy_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL)))
                return -ENOMEM;
        spin_lock_init(&PRIV(dev)->lock);
        memset(&PRIV(dev)->sonet_stats,0,sizeof(struct k_sonet_stats));
index 74cbbb2..456315b 100644 (file)
@@ -3978,11 +3978,15 @@ static int bond_neigh_init(struct neighbour *n)
 
        rcu_read_lock();
        slave = bond_first_slave_rcu(bond);
-       if (!slave)
+       if (!slave) {
+               ret = -EINVAL;
                goto out;
+       }
        slave_ops = slave->dev->netdev_ops;
-       if (!slave_ops->ndo_neigh_setup)
+       if (!slave_ops->ndo_neigh_setup) {
+               ret = -EINVAL;
                goto out;
+       }
 
        /* TODO: find another way [1] to implement this.
         * Passing a zeroed structure is fragile,
index 971ada3..134c057 100644 (file)
@@ -701,7 +701,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
        u32 reg;
 
        reg = priv->read(&regs->mcr);
-       reg |= FLEXCAN_MCR_HALT;
+       reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT;
        priv->write(reg, &regs->mcr);
 
        while (timeout-- && !(priv->read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
@@ -1480,10 +1480,13 @@ static int flexcan_chip_start(struct net_device *dev)
 
        flexcan_set_bittiming(dev);
 
+       /* set freeze, halt */
+       err = flexcan_chip_freeze(priv);
+       if (err)
+               goto out_chip_disable;
+
        /* MCR
         *
-        * enable freeze
-        * halt now
         * only supervisor access
         * enable warning int
         * enable individual RX masking
@@ -1492,9 +1495,8 @@ static int flexcan_chip_start(struct net_device *dev)
         */
        reg_mcr = priv->read(&regs->mcr);
        reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
-       reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV |
-               FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_IRMQ | FLEXCAN_MCR_IDAM_C |
-               FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
+       reg_mcr |= FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_IRMQ |
+               FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
 
        /* MCR
         *
@@ -1865,10 +1867,14 @@ static int register_flexcandev(struct net_device *dev)
        if (err)
                goto out_chip_disable;
 
-       /* set freeze, halt and activate FIFO, restrict register access */
+       /* set freeze, halt */
+       err = flexcan_chip_freeze(priv);
+       if (err)
+               goto out_chip_disable;
+
+       /* activate FIFO, restrict register access */
        reg = priv->read(&regs->mcr);
-       reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
-               FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
+       reg |=  FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
        priv->write(reg, &regs->mcr);
 
        /* Currently we only support newer versions of this core
index b7caec7..4147cec 100644 (file)
@@ -237,14 +237,14 @@ static int tcan4x5x_init(struct m_can_classdev *cdev)
        if (ret)
                return ret;
 
+       /* Zero out the MCAN buffers */
+       m_can_init_ram(cdev);
+
        ret = regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
                                 TCAN4X5X_MODE_SEL_MASK, TCAN4X5X_MODE_NORMAL);
        if (ret)
                return ret;
 
-       /* Zero out the MCAN buffers */
-       m_can_init_ram(cdev);
-
        return ret;
 }
 
index 3c5b929..799e9d5 100644 (file)
@@ -335,8 +335,6 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
        u8 len;
        int i, j;
 
-       netdev_reset_queue(priv->ndev);
-
        /* TEF */
        tef_ring = priv->tef;
        tef_ring->head = 0;
@@ -1249,8 +1247,7 @@ mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq)
 
 static int
 mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
-                          const struct mcp251xfd_hw_tef_obj *hw_tef_obj,
-                          unsigned int *frame_len_ptr)
+                          const struct mcp251xfd_hw_tef_obj *hw_tef_obj)
 {
        struct net_device_stats *stats = &priv->ndev->stats;
        u32 seq, seq_masked, tef_tail_masked;
@@ -1272,8 +1269,7 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
        stats->tx_bytes +=
                can_rx_offload_get_echo_skb(&priv->offload,
                                            mcp251xfd_get_tef_tail(priv),
-                                           hw_tef_obj->ts,
-                                           frame_len_ptr);
+                                           hw_tef_obj->ts, NULL);
        stats->tx_packets++;
        priv->tef->tail++;
 
@@ -1331,7 +1327,6 @@ mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv,
 static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
 {
        struct mcp251xfd_hw_tef_obj hw_tef_obj[MCP251XFD_TX_OBJ_NUM_MAX];
-       unsigned int total_frame_len = 0;
        u8 tef_tail, len, l;
        int err, i;
 
@@ -1353,9 +1348,7 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
        }
 
        for (i = 0; i < len; i++) {
-               unsigned int frame_len;
-
-               err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len);
+               err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i]);
                /* -EAGAIN means the Sequence Number in the TEF
                 * doesn't match our tef_tail. This can happen if we
                 * read the TEF objects too early. Leave loop let the
@@ -1365,8 +1358,6 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
                        goto out_netif_wake_queue;
                if (err)
                        return err;
-
-               total_frame_len += frame_len;
        }
 
  out_netif_wake_queue:
@@ -1397,7 +1388,6 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
                        return err;
 
                tx_ring->tail += len;
-               netdev_completed_queue(priv->ndev, len, total_frame_len);
 
                err = mcp251xfd_check_tef_tail(priv);
                if (err)
@@ -2443,7 +2433,6 @@ static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
        struct mcp251xfd_priv *priv = netdev_priv(ndev);
        struct mcp251xfd_tx_ring *tx_ring = priv->tx;
        struct mcp251xfd_tx_obj *tx_obj;
-       unsigned int frame_len;
        u8 tx_head;
        int err;
 
@@ -2462,9 +2451,7 @@ static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
        if (mcp251xfd_get_tx_free(tx_ring) == 0)
                netif_stop_queue(ndev);
 
-       frame_len = can_skb_get_frame_len(skb);
-       can_put_echo_skb(skb, ndev, tx_head, frame_len);
-       netdev_sent_queue(priv->ndev, frame_len);
+       can_put_echo_skb(skb, ndev, tx_head, 0);
 
        err = mcp251xfd_tx_obj_write(priv, tx_obj);
        if (err)
index 5ee8103..f277df9 100644 (file)
@@ -406,7 +406,7 @@ static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv)
        /* The watchdog reset does not work on 7278, we need to hit the
         * "external" reset line through the reset controller.
         */
-       if (priv->type == BCM7278_DEVICE_ID && !IS_ERR(priv->rcdev)) {
+       if (priv->type == BCM7278_DEVICE_ID) {
                ret = reset_control_assert(priv->rcdev);
                if (ret)
                        return ret;
@@ -1265,7 +1265,7 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
 
        priv->rcdev = devm_reset_control_get_optional_exclusive(&pdev->dev,
                                                                "switch");
-       if (PTR_ERR(priv->rcdev) == -EPROBE_DEFER)
+       if (IS_ERR(priv->rcdev))
                return PTR_ERR(priv->rcdev);
 
        /* Auto-detection using standard registers will not work, so
@@ -1426,7 +1426,7 @@ static int bcm_sf2_sw_remove(struct platform_device *pdev)
        bcm_sf2_mdio_unregister(priv);
        clk_disable_unprepare(priv->clk_mdiv);
        clk_disable_unprepare(priv->clk);
-       if (priv->type == BCM7278_DEVICE_ID && !IS_ERR(priv->rcdev))
+       if (priv->type == BCM7278_DEVICE_ID)
                reset_control_assert(priv->rcdev);
 
        return 0;
index c17de2b..f06f5fa 100644 (file)
@@ -1624,6 +1624,7 @@ mtk_get_tag_protocol(struct dsa_switch *ds, int port,
        }
 }
 
+#ifdef CONFIG_GPIOLIB
 static inline u32
 mt7530_gpio_to_bit(unsigned int offset)
 {
@@ -1726,6 +1727,7 @@ mt7530_setup_gpio(struct mt7530_priv *priv)
 
        return devm_gpiochip_add_data(dev, gc, priv);
 }
+#endif /* CONFIG_GPIOLIB */
 
 static int
 mt7530_setup(struct dsa_switch *ds)
@@ -1868,11 +1870,13 @@ mt7530_setup(struct dsa_switch *ds)
                }
        }
 
+#ifdef CONFIG_GPIOLIB
        if (of_property_read_bool(priv->dev->of_node, "gpio-controller")) {
                ret = mt7530_setup_gpio(priv);
                if (ret)
                        return ret;
        }
+#endif /* CONFIG_GPIOLIB */
 
        mt7530_setup_port5(ds, interface);
 
index 7692338..51ea104 100644 (file)
@@ -1922,7 +1922,7 @@ out_unlock_ptp:
                                speed = SPEED_1000;
                        else if (bmcr & BMCR_SPEED100)
                                speed = SPEED_100;
-                       else if (bmcr & BMCR_SPEED10)
+                       else
                                speed = SPEED_10;
 
                        sja1105_sgmii_pcs_force_speed(priv, speed);
@@ -3369,14 +3369,14 @@ static int sja1105_port_ucast_bcast_flood(struct sja1105_private *priv, int to,
                if (flags.val & BR_FLOOD)
                        priv->ucast_egress_floods |= BIT(to);
                else
-                       priv->ucast_egress_floods |= BIT(to);
+                       priv->ucast_egress_floods &= ~BIT(to);
        }
 
        if (flags.mask & BR_BCAST_FLOOD) {
                if (flags.val & BR_BCAST_FLOOD)
                        priv->bcast_egress_floods |= BIT(to);
                else
-                       priv->bcast_egress_floods |= BIT(to);
+                       priv->bcast_egress_floods &= ~BIT(to);
        }
 
        return sja1105_manage_flood_domains(priv);
index f025f96..fde6e99 100644 (file)
@@ -528,7 +528,10 @@ static int xrs700x_hsr_join(struct dsa_switch *ds, int port,
                return -EOPNOTSUPP;
 
        dsa_hsr_foreach_port(dp, ds, hsr) {
-               partner = dp;
+               if (dp->index != port) {
+                       partner = dp;
+                       break;
+               }
        }
 
        /* We can't enable redundancy on the switch until both
@@ -582,7 +585,10 @@ static int xrs700x_hsr_leave(struct dsa_switch *ds, int port,
        unsigned int val;
 
        dsa_hsr_foreach_port(dp, ds, hsr) {
-               partner = dp;
+               if (dp->index != port) {
+                       partner = dp;
+                       break;
+               }
        }
 
        if (!partner)
index 9b7f1af..9e02f88 100644 (file)
@@ -1894,13 +1894,16 @@ static int alx_resume(struct device *dev)
 
        if (!netif_running(alx->dev))
                return 0;
-       netif_device_attach(alx->dev);
 
        rtnl_lock();
        err = __alx_open(alx, true);
        rtnl_unlock();
+       if (err)
+               return err;
 
-       return err;
+       netif_device_attach(alx->dev);
+
+       return 0;
 }
 
 static SIMPLE_DEV_PM_OPS(alx_pm_ops, alx_suspend, alx_resume);
index 0b70e9e..98cf82d 100644 (file)
@@ -592,6 +592,9 @@ static int bcm4908_enet_poll(struct napi_struct *napi, int weight)
                bcm4908_enet_intrs_on(enet);
        }
 
+       /* Hardware could disable ring if it run out of descriptors */
+       bcm4908_enet_dma_rx_ring_enable(enet, &enet->rx_ring);
+
        return handled;
 }
 
index a680fd9..b53a0d8 100644 (file)
@@ -8556,10 +8556,18 @@ static void bnxt_setup_inta(struct bnxt *bp)
        bp->irq_tbl[0].handler = bnxt_inta;
 }
 
+static int bnxt_init_int_mode(struct bnxt *bp);
+
 static int bnxt_setup_int_mode(struct bnxt *bp)
 {
        int rc;
 
+       if (!bp->irq_tbl) {
+               rc = bnxt_init_int_mode(bp);
+               if (rc || !bp->irq_tbl)
+                       return rc ?: -ENODEV;
+       }
+
        if (bp->flags & BNXT_FLAG_USING_MSIX)
                bnxt_setup_msix(bp);
        else
@@ -8744,7 +8752,7 @@ static int bnxt_init_inta(struct bnxt *bp)
 
 static int bnxt_init_int_mode(struct bnxt *bp)
 {
-       int rc = 0;
+       int rc = -ENODEV;
 
        if (bp->flags & BNXT_FLAG_MSIX_CAP)
                rc = bnxt_init_msix(bp);
@@ -9514,7 +9522,8 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
 {
        struct hwrm_func_drv_if_change_output *resp = bp->hwrm_cmd_resp_addr;
        struct hwrm_func_drv_if_change_input req = {0};
-       bool resc_reinit = false, fw_reset = false;
+       bool fw_reset = !bp->irq_tbl;
+       bool resc_reinit = false;
        int rc, retry = 0;
        u32 flags = 0;
 
@@ -9557,6 +9566,7 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
 
        if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state) && !fw_reset) {
                netdev_err(bp->dev, "RESET_DONE not set during FW reset.\n");
+               set_bit(BNXT_STATE_ABORT_ERR, &bp->state);
                return -ENODEV;
        }
        if (resc_reinit || fw_reset) {
@@ -9890,6 +9900,9 @@ static int bnxt_reinit_after_abort(struct bnxt *bp)
        if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
                return -EBUSY;
 
+       if (bp->dev->reg_state == NETREG_UNREGISTERED)
+               return -ENODEV;
+
        rc = bnxt_fw_init_one(bp);
        if (!rc) {
                bnxt_clear_int_mode(bp);
index 472bf8f..15362d0 100644 (file)
@@ -3954,6 +3954,13 @@ static int macb_init(struct platform_device *pdev)
        return 0;
 }
 
+static const struct macb_usrio_config macb_default_usrio = {
+       .mii = MACB_BIT(MII),
+       .rmii = MACB_BIT(RMII),
+       .rgmii = GEM_BIT(RGMII),
+       .refclk = MACB_BIT(CLKEN),
+};
+
 #if defined(CONFIG_OF)
 /* 1518 rounded up */
 #define AT91ETHER_MAX_RBUFF_SZ 0x600
@@ -4439,13 +4446,6 @@ static int fu540_c000_init(struct platform_device *pdev)
        return macb_init(pdev);
 }
 
-static const struct macb_usrio_config macb_default_usrio = {
-       .mii = MACB_BIT(MII),
-       .rmii = MACB_BIT(RMII),
-       .rgmii = GEM_BIT(RGMII),
-       .refclk = MACB_BIT(CLKEN),
-};
-
 static const struct macb_usrio_config sama7g5_usrio = {
        .mii = 0,
        .rmii = 1,
@@ -4594,6 +4594,7 @@ static const struct macb_config default_gem_config = {
        .dma_burst_length = 16,
        .clk_init = macb_clk_init,
        .init = macb_init,
+       .usrio = &macb_default_usrio,
        .jumbo_max_len = 10240,
 };
 
index 46a809f..169e10c 100644 (file)
@@ -672,7 +672,7 @@ static int chcr_ktls_cpl_act_open_rpl(struct adapter *adap,
        if (tx_info->pending_close) {
                spin_unlock(&tx_info->lock);
                if (!status) {
-                       /* it's a late success, tcb status is establised,
+                       /* it's a late success, tcb status is established,
                         * mark it close.
                         */
                        chcr_ktls_mark_tcb_close(tx_info);
@@ -930,7 +930,7 @@ chcr_ktls_get_tx_flits(u32 nr_frags, unsigned int key_ctx_len)
 }
 
 /*
- * chcr_ktls_check_tcp_options: To check if there is any TCP option availbale
+ * chcr_ktls_check_tcp_options: To check if there is any TCP option available
  * other than timestamp.
  * @skb - skb contains partial record..
  * return: 1 / 0
@@ -1115,7 +1115,7 @@ static int chcr_ktls_xmit_wr_complete(struct sk_buff *skb,
        }
 
        if (unlikely(credits < ETHTXQ_STOP_THRES)) {
-               /* Credits are below the threshold vaues, stop the queue after
+               /* Credits are below the threshold values, stop the queue after
                 * injecting the Work Request for this packet.
                 */
                chcr_eth_txq_stop(q);
@@ -2006,7 +2006,7 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* TCP segments can be in received either complete or partial.
         * chcr_end_part_handler will handle cases if complete record or end
-        * part of the record is received. Incase of partial end part of record,
+        * part of the record is received. In case of partial end part of record,
         * we will send the complete record again.
         */
 
index 3fdc70d..252adfa 100644 (file)
@@ -133,6 +133,8 @@ struct board_info {
        u32             wake_state;
 
        int             ip_summed;
+
+       struct regulator *power_supply;
 };
 
 /* debug code */
@@ -1449,7 +1451,7 @@ dm9000_probe(struct platform_device *pdev)
                if (ret) {
                        dev_err(dev, "failed to request reset gpio %d: %d\n",
                                reset_gpios, ret);
-                       return -ENODEV;
+                       goto out_regulator_disable;
                }
 
                /* According to manual PWRST# Low Period Min 1ms */
@@ -1461,8 +1463,10 @@ dm9000_probe(struct platform_device *pdev)
 
        if (!pdata) {
                pdata = dm9000_parse_dt(&pdev->dev);
-               if (IS_ERR(pdata))
-                       return PTR_ERR(pdata);
+               if (IS_ERR(pdata)) {
+                       ret = PTR_ERR(pdata);
+                       goto out_regulator_disable;
+               }
        }
 
        /* Init network device */
@@ -1479,6 +1483,8 @@ dm9000_probe(struct platform_device *pdev)
 
        db->dev = &pdev->dev;
        db->ndev = ndev;
+       if (!IS_ERR(power))
+               db->power_supply = power;
 
        spin_lock_init(&db->lock);
        mutex_init(&db->addr_lock);
@@ -1501,7 +1507,7 @@ dm9000_probe(struct platform_device *pdev)
                goto out;
        }
 
-       db->irq_wake = platform_get_irq(pdev, 1);
+       db->irq_wake = platform_get_irq_optional(pdev, 1);
        if (db->irq_wake >= 0) {
                dev_dbg(db->dev, "wakeup irq %d\n", db->irq_wake);
 
@@ -1703,6 +1709,10 @@ out:
        dm9000_release_board(pdev, db);
        free_netdev(ndev);
 
+out_regulator_disable:
+       if (!IS_ERR(power))
+               regulator_disable(power);
+
        return ret;
 }
 
@@ -1760,10 +1770,13 @@ static int
 dm9000_drv_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
+       struct board_info *dm = to_dm9000_board(ndev);
 
        unregister_netdev(ndev);
-       dm9000_release_board(pdev, netdev_priv(ndev));
+       dm9000_release_board(pdev, dm);
        free_netdev(ndev);              /* free device structure */
+       if (dm->power_supply)
+               regulator_disable(dm->power_supply);
 
        dev_dbg(&pdev->dev, "released and freed device\n");
        return 0;
index c78d122..0947132 100644 (file)
@@ -281,6 +281,8 @@ static int enetc_poll(struct napi_struct *napi, int budget)
        int work_done;
        int i;
 
+       enetc_lock_mdio();
+
        for (i = 0; i < v->count_tx_rings; i++)
                if (!enetc_clean_tx_ring(&v->tx_ring[i], budget))
                        complete = false;
@@ -291,8 +293,10 @@ static int enetc_poll(struct napi_struct *napi, int budget)
        if (work_done)
                v->rx_napi_work = true;
 
-       if (!complete)
+       if (!complete) {
+               enetc_unlock_mdio();
                return budget;
+       }
 
        napi_complete_done(napi, work_done);
 
@@ -301,8 +305,6 @@ static int enetc_poll(struct napi_struct *napi, int budget)
 
        v->rx_napi_work = false;
 
-       enetc_lock_mdio();
-
        /* enable interrupts */
        enetc_wr_reg_hot(v->rbier, ENETC_RBIER_RXTIE);
 
@@ -327,8 +329,8 @@ static void enetc_get_tx_tstamp(struct enetc_hw *hw, union enetc_tx_bd *txbd,
 {
        u32 lo, hi, tstamp_lo;
 
-       lo = enetc_rd(hw, ENETC_SICTR0);
-       hi = enetc_rd(hw, ENETC_SICTR1);
+       lo = enetc_rd_hot(hw, ENETC_SICTR0);
+       hi = enetc_rd_hot(hw, ENETC_SICTR1);
        tstamp_lo = le32_to_cpu(txbd->wb.tstamp);
        if (lo <= tstamp_lo)
                hi -= 1;
@@ -342,6 +344,12 @@ static void enetc_tstamp_tx(struct sk_buff *skb, u64 tstamp)
        if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) {
                memset(&shhwtstamps, 0, sizeof(shhwtstamps));
                shhwtstamps.hwtstamp = ns_to_ktime(tstamp);
+               /* Ensure skb_mstamp_ns, which might have been populated with
+                * the txtime, is not mistaken for a software timestamp,
+                * because this will prevent the dispatch of our hardware
+                * timestamp to the socket.
+                */
+               skb->tstamp = ktime_set(0, 0);
                skb_tstamp_tx(skb, &shhwtstamps);
        }
 }
@@ -358,9 +366,7 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
        i = tx_ring->next_to_clean;
        tx_swbd = &tx_ring->tx_swbd[i];
 
-       enetc_lock_mdio();
        bds_to_clean = enetc_bd_ready_count(tx_ring, i);
-       enetc_unlock_mdio();
 
        do_tstamp = false;
 
@@ -403,8 +409,6 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
                        tx_swbd = tx_ring->tx_swbd;
                }
 
-               enetc_lock_mdio();
-
                /* BD iteration loop end */
                if (is_eof) {
                        tx_frm_cnt++;
@@ -415,8 +419,6 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
 
                if (unlikely(!bds_to_clean))
                        bds_to_clean = enetc_bd_ready_count(tx_ring, i);
-
-               enetc_unlock_mdio();
        }
 
        tx_ring->next_to_clean = i;
@@ -527,9 +529,8 @@ static void enetc_get_rx_tstamp(struct net_device *ndev,
 static void enetc_get_offloads(struct enetc_bdr *rx_ring,
                               union enetc_rx_bd *rxbd, struct sk_buff *skb)
 {
-#ifdef CONFIG_FSL_ENETC_PTP_CLOCK
        struct enetc_ndev_priv *priv = netdev_priv(rx_ring->ndev);
-#endif
+
        /* TODO: hashing */
        if (rx_ring->ndev->features & NETIF_F_RXCSUM) {
                u16 inet_csum = le16_to_cpu(rxbd->r.inet_csum);
@@ -538,12 +539,31 @@ static void enetc_get_offloads(struct enetc_bdr *rx_ring,
                skb->ip_summed = CHECKSUM_COMPLETE;
        }
 
-       /* copy VLAN to skb, if one is extracted, for now we assume it's a
-        * standard TPID, but HW also supports custom values
-        */
-       if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_VLAN)
-               __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
-                                      le16_to_cpu(rxbd->r.vlan_opt));
+       if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_VLAN) {
+               __be16 tpid = 0;
+
+               switch (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_TPID) {
+               case 0:
+                       tpid = htons(ETH_P_8021Q);
+                       break;
+               case 1:
+                       tpid = htons(ETH_P_8021AD);
+                       break;
+               case 2:
+                       tpid = htons(enetc_port_rd(&priv->si->hw,
+                                                  ENETC_PCVLANR1));
+                       break;
+               case 3:
+                       tpid = htons(enetc_port_rd(&priv->si->hw,
+                                                  ENETC_PCVLANR2));
+                       break;
+               default:
+                       break;
+               }
+
+               __vlan_hwaccel_put_tag(skb, tpid, le16_to_cpu(rxbd->r.vlan_opt));
+       }
+
 #ifdef CONFIG_FSL_ENETC_PTP_CLOCK
        if (priv->active_offloads & ENETC_F_RX_TSTAMP)
                enetc_get_rx_tstamp(rx_ring->ndev, rxbd, skb);
@@ -660,8 +680,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
                u32 bd_status;
                u16 size;
 
-               enetc_lock_mdio();
-
                if (cleaned_cnt >= ENETC_RXBD_BUNDLE) {
                        int count = enetc_refill_rx_ring(rx_ring, cleaned_cnt);
 
@@ -672,19 +690,15 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
 
                rxbd = enetc_rxbd(rx_ring, i);
                bd_status = le32_to_cpu(rxbd->r.lstatus);
-               if (!bd_status) {
-                       enetc_unlock_mdio();
+               if (!bd_status)
                        break;
-               }
 
                enetc_wr_reg_hot(rx_ring->idr, BIT(rx_ring->index));
                dma_rmb(); /* for reading other rxbd fields */
                size = le16_to_cpu(rxbd->r.buf_len);
                skb = enetc_map_rx_buff_to_skb(rx_ring, i, size);
-               if (!skb) {
-                       enetc_unlock_mdio();
+               if (!skb)
                        break;
-               }
 
                enetc_get_offloads(rx_ring, rxbd, skb);
 
@@ -696,7 +710,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
 
                if (unlikely(bd_status &
                             ENETC_RXBD_LSTATUS(ENETC_RXBD_ERR_MASK))) {
-                       enetc_unlock_mdio();
                        dev_kfree_skb(skb);
                        while (!(bd_status & ENETC_RXBD_LSTATUS_F)) {
                                dma_rmb();
@@ -736,8 +749,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
 
                enetc_process_skb(rx_ring, skb);
 
-               enetc_unlock_mdio();
-
                napi_gro_receive(napi, skb);
 
                rx_frm_cnt++;
@@ -984,7 +995,7 @@ static void enetc_free_rxtx_rings(struct enetc_ndev_priv *priv)
                enetc_free_tx_ring(priv->tx_ring[i]);
 }
 
-static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
+int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
 {
        int size = cbdr->bd_count * sizeof(struct enetc_cbd);
 
@@ -1005,7 +1016,7 @@ static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
        return 0;
 }
 
-static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
+void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
 {
        int size = cbdr->bd_count * sizeof(struct enetc_cbd);
 
@@ -1013,7 +1024,7 @@ static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
        cbdr->bd_base = NULL;
 }
 
-static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
+void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
 {
        /* set CBDR cache attributes */
        enetc_wr(hw, ENETC_SICAR2,
@@ -1033,7 +1044,7 @@ static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
        cbdr->cir = hw->reg + ENETC_SICBDRCIR;
 }
 
-static void enetc_clear_cbdr(struct enetc_hw *hw)
+void enetc_clear_cbdr(struct enetc_hw *hw)
 {
        enetc_wr(hw, ENETC_SICBDRMR, 0);
 }
@@ -1058,13 +1069,12 @@ static int enetc_setup_default_rss_table(struct enetc_si *si, int num_groups)
        return 0;
 }
 
-static int enetc_configure_si(struct enetc_ndev_priv *priv)
+int enetc_configure_si(struct enetc_ndev_priv *priv)
 {
        struct enetc_si *si = priv->si;
        struct enetc_hw *hw = &si->hw;
        int err;
 
-       enetc_setup_cbdr(hw, &si->cbd_ring);
        /* set SI cache attributes */
        enetc_wr(hw, ENETC_SICAR0,
                 ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
@@ -1112,6 +1122,8 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv)
        if (err)
                return err;
 
+       enetc_setup_cbdr(&si->hw, &si->cbd_ring);
+
        priv->cls_rules = kcalloc(si->num_fs_entries, sizeof(*priv->cls_rules),
                                  GFP_KERNEL);
        if (!priv->cls_rules) {
@@ -1119,14 +1131,8 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv)
                goto err_alloc_cls;
        }
 
-       err = enetc_configure_si(priv);
-       if (err)
-               goto err_config_si;
-
        return 0;
 
-err_config_si:
-       kfree(priv->cls_rules);
 err_alloc_cls:
        enetc_clear_cbdr(&si->hw);
        enetc_free_cbdr(priv->dev, &si->cbd_ring);
@@ -1212,7 +1218,8 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
        rx_ring->idr = hw->reg + ENETC_SIRXIDR;
 
        enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring));
-       enetc_wr(hw, ENETC_SIRXIDR, rx_ring->next_to_use);
+       /* update ENETC's consumer index */
+       enetc_rxbdr_wr(hw, idx, ENETC_RBCIR, rx_ring->next_to_use);
 
        /* enable ring */
        enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
index 8532d23..8b380fc 100644 (file)
@@ -292,6 +292,7 @@ void enetc_get_si_caps(struct enetc_si *si);
 void enetc_init_si_rings_params(struct enetc_ndev_priv *priv);
 int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
 void enetc_free_si_resources(struct enetc_ndev_priv *priv);
+int enetc_configure_si(struct enetc_ndev_priv *priv);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
@@ -309,6 +310,10 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
 void enetc_set_ethtool_ops(struct net_device *ndev);
 
 /* control buffer descriptor ring (CBDR) */
+int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr);
+void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr);
+void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr);
+void enetc_clear_cbdr(struct enetc_hw *hw);
 int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
                            char *mac_addr, int si_map);
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
index c71fe8d..00938f7 100644 (file)
@@ -172,6 +172,8 @@ enum enetc_bdr_type {TX, RX};
 #define ENETC_PSIPMAR0(n)      (0x0100 + (n) * 0x8) /* n = SI index */
 #define ENETC_PSIPMAR1(n)      (0x0104 + (n) * 0x8)
 #define ENETC_PVCLCTR          0x0208
+#define ENETC_PCVLANR1         0x0210
+#define ENETC_PCVLANR2         0x0214
 #define ENETC_VLAN_TYPE_C      BIT(0)
 #define ENETC_VLAN_TYPE_S      BIT(1)
 #define ENETC_PVCLCTR_OVTPIDL(bmp)     ((bmp) & 0xff) /* VLAN_TYPE */
@@ -232,14 +234,23 @@ enum enetc_bdr_type {TX, RX};
 #define ENETC_PM0_MAXFRM       0x8014
 #define ENETC_SET_TX_MTU(val)  ((val) << 16)
 #define ENETC_SET_MAXFRM(val)  ((val) & 0xffff)
+#define ENETC_PM0_RX_FIFO      0x801c
+#define ENETC_PM0_RX_FIFO_VAL  1
 
 #define ENETC_PM_IMDIO_BASE    0x8030
 
 #define ENETC_PM0_IF_MODE      0x8300
-#define ENETC_PMO_IFM_RG       BIT(2)
+#define ENETC_PM0_IFM_RG       BIT(2)
 #define ENETC_PM0_IFM_RLP      (BIT(5) | BIT(11))
-#define ENETC_PM0_IFM_RGAUTO   (BIT(15) | ENETC_PMO_IFM_RG | BIT(1))
-#define ENETC_PM0_IFM_XGMII    BIT(12)
+#define ENETC_PM0_IFM_EN_AUTO  BIT(15)
+#define ENETC_PM0_IFM_SSP_MASK GENMASK(14, 13)
+#define ENETC_PM0_IFM_SSP_1000 (2 << 13)
+#define ENETC_PM0_IFM_SSP_100  (0 << 13)
+#define ENETC_PM0_IFM_SSP_10   (1 << 13)
+#define ENETC_PM0_IFM_FULL_DPX BIT(12)
+#define ENETC_PM0_IFM_IFMODE_MASK GENMASK(1, 0)
+#define ENETC_PM0_IFM_IFMODE_XGMII 0
+#define ENETC_PM0_IFM_IFMODE_GMII 2
 #define ENETC_PSIDCAPR         0x1b08
 #define ENETC_PSIDCAPR_MSK     GENMASK(15, 0)
 #define ENETC_PSFCAPR          0x1b18
@@ -453,6 +464,8 @@ static inline u64 _enetc_rd_reg64_wa(void __iomem *reg)
 #define enetc_wr_reg(reg, val)         _enetc_wr_reg_wa((reg), (val))
 #define enetc_rd(hw, off)              enetc_rd_reg((hw)->reg + (off))
 #define enetc_wr(hw, off, val)         enetc_wr_reg((hw)->reg + (off), val)
+#define enetc_rd_hot(hw, off)          enetc_rd_reg_hot((hw)->reg + (off))
+#define enetc_wr_hot(hw, off, val)     enetc_wr_reg_hot((hw)->reg + (off), val)
 #define enetc_rd64(hw, off)            _enetc_rd_reg64_wa((hw)->reg + (off))
 /* port register accessors - PF only */
 #define enetc_port_rd(hw, off)         enetc_rd_reg((hw)->port + (off))
@@ -568,6 +581,7 @@ union enetc_rx_bd {
 #define ENETC_RXBD_LSTATUS(flags)      ((flags) << 16)
 #define ENETC_RXBD_FLAG_VLAN   BIT(9)
 #define ENETC_RXBD_FLAG_TSTMP  BIT(10)
+#define ENETC_RXBD_FLAG_TPID   GENMASK(1, 0)
 
 #define ENETC_MAC_ADDR_FILT_CNT        8 /* # of supported entries per port */
 #define EMETC_MAC_ADDR_FILT_RES        3 /* # of reserved entries at the beginning */
index 515c5b2..224fc37 100644 (file)
@@ -190,7 +190,6 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
 {
        struct enetc_ndev_priv *priv = netdev_priv(ndev);
        struct enetc_pf *pf = enetc_si_priv(priv->si);
-       char vlan_promisc_simap = pf->vlan_promisc_simap;
        struct enetc_hw *hw = &priv->si->hw;
        bool uprom = false, mprom = false;
        struct enetc_mac_filter *filter;
@@ -203,16 +202,12 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
                psipmr = ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0);
                uprom = true;
                mprom = true;
-               /* Enable VLAN promiscuous mode for SI0 (PF) */
-               vlan_promisc_simap |= BIT(0);
        } else if (ndev->flags & IFF_ALLMULTI) {
                /* enable multi cast promisc mode for SI0 (PF) */
                psipmr = ENETC_PSIPMR_SET_MP(0);
                mprom = true;
        }
 
-       enetc_set_vlan_promisc(&pf->si->hw, vlan_promisc_simap);
-
        /* first 2 filter entries belong to PF */
        if (!uprom) {
                /* Update unicast filters */
@@ -320,7 +315,7 @@ static void enetc_set_loopback(struct net_device *ndev, bool en)
        u32 reg;
 
        reg = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
-       if (reg & ENETC_PMO_IFM_RG) {
+       if (reg & ENETC_PM0_IFM_RG) {
                /* RGMII mode */
                reg = (reg & ~ENETC_PM0_IFM_RLP) |
                      (en ? ENETC_PM0_IFM_RLP : 0);
@@ -495,17 +490,30 @@ static void enetc_configure_port_mac(struct enetc_hw *hw)
 
        enetc_port_wr(hw, ENETC_PM1_CMD_CFG, ENETC_PM0_CMD_PHY_TX_EN |
                      ENETC_PM0_CMD_TXP | ENETC_PM0_PROMISC);
+
+       /* On LS1028A, the MAC RX FIFO defaults to 2, which is too high
+        * and may lead to RX lock-up under traffic. Set it to 1 instead,
+        * as recommended by the hardware team.
+        */
+       enetc_port_wr(hw, ENETC_PM0_RX_FIFO, ENETC_PM0_RX_FIFO_VAL);
 }
 
 static void enetc_mac_config(struct enetc_hw *hw, phy_interface_t phy_mode)
 {
-       /* set auto-speed for RGMII */
-       if (enetc_port_rd(hw, ENETC_PM0_IF_MODE) & ENETC_PMO_IFM_RG ||
-           phy_interface_mode_is_rgmii(phy_mode))
-               enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_RGAUTO);
+       u32 val;
+
+       if (phy_interface_mode_is_rgmii(phy_mode)) {
+               val = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
+               val &= ~ENETC_PM0_IFM_EN_AUTO;
+               val &= ENETC_PM0_IFM_IFMODE_MASK;
+               val |= ENETC_PM0_IFM_IFMODE_GMII | ENETC_PM0_IFM_RG;
+               enetc_port_wr(hw, ENETC_PM0_IF_MODE, val);
+       }
 
-       if (phy_mode == PHY_INTERFACE_MODE_USXGMII)
-               enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_XGMII);
+       if (phy_mode == PHY_INTERFACE_MODE_USXGMII) {
+               val = ENETC_PM0_IFM_FULL_DPX | ENETC_PM0_IFM_IFMODE_XGMII;
+               enetc_port_wr(hw, ENETC_PM0_IF_MODE, val);
+       }
 }
 
 static void enetc_mac_enable(struct enetc_hw *hw, bool en)
@@ -937,6 +945,34 @@ static void enetc_pl_mac_config(struct phylink_config *config,
                phylink_set_pcs(priv->phylink, &pf->pcs->pcs);
 }
 
+static void enetc_force_rgmii_mac(struct enetc_hw *hw, int speed, int duplex)
+{
+       u32 old_val, val;
+
+       old_val = val = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
+
+       if (speed == SPEED_1000) {
+               val &= ~ENETC_PM0_IFM_SSP_MASK;
+               val |= ENETC_PM0_IFM_SSP_1000;
+       } else if (speed == SPEED_100) {
+               val &= ~ENETC_PM0_IFM_SSP_MASK;
+               val |= ENETC_PM0_IFM_SSP_100;
+       } else if (speed == SPEED_10) {
+               val &= ~ENETC_PM0_IFM_SSP_MASK;
+               val |= ENETC_PM0_IFM_SSP_10;
+       }
+
+       if (duplex == DUPLEX_FULL)
+               val |= ENETC_PM0_IFM_FULL_DPX;
+       else
+               val &= ~ENETC_PM0_IFM_FULL_DPX;
+
+       if (val == old_val)
+               return;
+
+       enetc_port_wr(hw, ENETC_PM0_IF_MODE, val);
+}
+
 static void enetc_pl_mac_link_up(struct phylink_config *config,
                                 struct phy_device *phy, unsigned int mode,
                                 phy_interface_t interface, int speed,
@@ -949,6 +985,10 @@ static void enetc_pl_mac_link_up(struct phylink_config *config,
        if (priv->active_offloads & ENETC_F_QBV)
                enetc_sched_speed_set(priv, speed);
 
+       if (!phylink_autoneg_inband(mode) &&
+           phy_interface_mode_is_rgmii(interface))
+               enetc_force_rgmii_mac(&pf->si->hw, speed, duplex);
+
        enetc_mac_enable(&pf->si->hw, true);
 }
 
@@ -1041,6 +1081,26 @@ static int enetc_init_port_rss_memory(struct enetc_si *si)
        return err;
 }
 
+static void enetc_init_unused_port(struct enetc_si *si)
+{
+       struct device *dev = &si->pdev->dev;
+       struct enetc_hw *hw = &si->hw;
+       int err;
+
+       si->cbd_ring.bd_count = ENETC_CBDR_DEFAULT_SIZE;
+       err = enetc_alloc_cbdr(dev, &si->cbd_ring);
+       if (err)
+               return;
+
+       enetc_setup_cbdr(hw, &si->cbd_ring);
+
+       enetc_init_port_rfs_memory(si);
+       enetc_init_port_rss_memory(si);
+
+       enetc_clear_cbdr(hw);
+       enetc_free_cbdr(dev, &si->cbd_ring);
+}
+
 static int enetc_pf_probe(struct pci_dev *pdev,
                          const struct pci_device_id *ent)
 {
@@ -1051,11 +1111,6 @@ static int enetc_pf_probe(struct pci_dev *pdev,
        struct enetc_pf *pf;
        int err;
 
-       if (node && !of_device_is_available(node)) {
-               dev_info(&pdev->dev, "device is disabled, skipping\n");
-               return -ENODEV;
-       }
-
        err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf));
        if (err) {
                dev_err(&pdev->dev, "PCI probing failed\n");
@@ -1069,6 +1124,13 @@ static int enetc_pf_probe(struct pci_dev *pdev,
                goto err_map_pf_space;
        }
 
+       if (node && !of_device_is_available(node)) {
+               enetc_init_unused_port(si);
+               dev_info(&pdev->dev, "device is disabled, skipping\n");
+               err = -ENODEV;
+               goto err_device_disabled;
+       }
+
        pf = enetc_si_priv(si);
        pf->si = si;
        pf->total_vfs = pci_sriov_get_totalvfs(pdev);
@@ -1108,6 +1170,12 @@ static int enetc_pf_probe(struct pci_dev *pdev,
                goto err_init_port_rss;
        }
 
+       err = enetc_configure_si(priv);
+       if (err) {
+               dev_err(&pdev->dev, "Failed to configure SI\n");
+               goto err_config_si;
+       }
+
        err = enetc_alloc_msix(priv);
        if (err) {
                dev_err(&pdev->dev, "MSIX alloc failed\n");
@@ -1136,6 +1204,7 @@ err_phylink_create:
        enetc_mdiobus_destroy(pf);
 err_mdiobus_create:
        enetc_free_msix(priv);
+err_config_si:
 err_init_port_rss:
 err_init_port_rfs:
 err_alloc_msix:
@@ -1144,6 +1213,7 @@ err_alloc_si_res:
        si->ndev = NULL;
        free_netdev(ndev);
 err_alloc_netdev:
+err_device_disabled:
 err_map_pf_space:
        enetc_pci_remove(pdev);
 
index 39c1a09..9b755a8 100644 (file)
@@ -171,6 +171,12 @@ static int enetc_vf_probe(struct pci_dev *pdev,
                goto err_alloc_si_res;
        }
 
+       err = enetc_configure_si(priv);
+       if (err) {
+               dev_err(&pdev->dev, "Failed to configure SI\n");
+               goto err_config_si;
+       }
+
        err = enetc_alloc_msix(priv);
        if (err) {
                dev_err(&pdev->dev, "MSIX alloc failed\n");
@@ -187,6 +193,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
 
 err_reg_netdev:
        enetc_free_msix(priv);
+err_config_si:
 err_alloc_msix:
        enetc_free_si_resources(priv);
 err_alloc_si_res:
index 2e344aa..1753807 100644 (file)
@@ -377,9 +377,16 @@ static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
        u64 ns;
        unsigned long flags;
 
+       mutex_lock(&adapter->ptp_clk_mutex);
+       /* Check the ptp clock */
+       if (!adapter->ptp_clk_on) {
+               mutex_unlock(&adapter->ptp_clk_mutex);
+               return -EINVAL;
+       }
        spin_lock_irqsave(&adapter->tmreg_lock, flags);
        ns = timecounter_read(&adapter->tc);
        spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+       mutex_unlock(&adapter->ptp_clk_mutex);
 
        *ts = ns_to_timespec64(ns);
 
index 541de32..1cf8ef7 100644 (file)
@@ -2390,6 +2390,10 @@ static bool gfar_add_rx_frag(struct gfar_rx_buff *rxb, u32 lstatus,
                if (lstatus & BD_LFLAG(RXBD_LAST))
                        size -= skb->len;
 
+               WARN(size < 0, "gianfar: rx fragment size underflow");
+               if (size < 0)
+                       return false;
+
                skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
                                rxb->page_offset + RXBUF_ALIGNMENT,
                                size, GFAR_RXB_TRUESIZE);
@@ -2552,6 +2556,17 @@ static int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue,
                if (lstatus & BD_LFLAG(RXBD_EMPTY))
                        break;
 
+               /* lost RXBD_LAST descriptor due to overrun */
+               if (skb &&
+                   (lstatus & BD_LFLAG(RXBD_FIRST))) {
+                       /* discard faulty buffer */
+                       dev_kfree_skb(skb);
+                       skb = NULL;
+                       rx_queue->stats.rx_dropped++;
+
+                       /* can continue normally */
+               }
+
                /* order rx buffer descriptor reads */
                rmb();
 
index 5d7824d..c66a7a5 100644 (file)
@@ -1663,8 +1663,10 @@ static int hns_nic_clear_all_rx_fetch(struct net_device *ndev)
                        for (j = 0; j < fetch_num; j++) {
                                /* alloc one skb and init */
                                skb = hns_assemble_skb(ndev);
-                               if (!skb)
+                               if (!skb) {
+                                       ret = -ENOMEM;
                                        goto out;
+                               }
                                rd = &tx_ring_data(priv, skb->queue_mapping);
                                hns_nic_net_xmit_hw(ndev, skb, rd);
 
index ff52a65..057dda7 100644 (file)
@@ -1053,16 +1053,16 @@ struct hclge_fd_tcam_config_3_cmd {
 #define HCLGE_FD_AD_DROP_B             0
 #define HCLGE_FD_AD_DIRECT_QID_B       1
 #define HCLGE_FD_AD_QID_S              2
-#define HCLGE_FD_AD_QID_M              GENMASK(12, 2)
+#define HCLGE_FD_AD_QID_M              GENMASK(11, 2)
 #define HCLGE_FD_AD_USE_COUNTER_B      12
 #define HCLGE_FD_AD_COUNTER_NUM_S      13
 #define HCLGE_FD_AD_COUNTER_NUM_M      GENMASK(20, 13)
 #define HCLGE_FD_AD_NXT_STEP_B         20
 #define HCLGE_FD_AD_NXT_KEY_S          21
-#define HCLGE_FD_AD_NXT_KEY_M          GENMASK(26, 21)
+#define HCLGE_FD_AD_NXT_KEY_M          GENMASK(25, 21)
 #define HCLGE_FD_AD_WR_RULE_ID_B       0
 #define HCLGE_FD_AD_RULE_ID_S          1
-#define HCLGE_FD_AD_RULE_ID_M          GENMASK(13, 1)
+#define HCLGE_FD_AD_RULE_ID_M          GENMASK(12, 1)
 #define HCLGE_FD_AD_TC_OVRD_B          16
 #define HCLGE_FD_AD_TC_SIZE_S          17
 #define HCLGE_FD_AD_TC_SIZE_M          GENMASK(20, 17)
index 34b744d..e3f81c7 100644 (file)
@@ -5245,9 +5245,9 @@ static bool hclge_fd_convert_tuple(u32 tuple_bit, u8 *key_x, u8 *key_y,
        case BIT(INNER_SRC_MAC):
                for (i = 0; i < ETH_ALEN; i++) {
                        calc_x(key_x[ETH_ALEN - 1 - i], rule->tuples.src_mac[i],
-                              rule->tuples.src_mac[i]);
+                              rule->tuples_mask.src_mac[i]);
                        calc_y(key_y[ETH_ALEN - 1 - i], rule->tuples.src_mac[i],
-                              rule->tuples.src_mac[i]);
+                              rule->tuples_mask.src_mac[i]);
                }
 
                return true;
@@ -6330,8 +6330,7 @@ static void hclge_fd_get_ext_info(struct ethtool_rx_flow_spec *fs,
                fs->h_ext.vlan_tci = cpu_to_be16(rule->tuples.vlan_tag1);
                fs->m_ext.vlan_tci =
                                rule->unused_tuple & BIT(INNER_VLAN_TAG_FST) ?
-                               cpu_to_be16(VLAN_VID_MASK) :
-                               cpu_to_be16(rule->tuples_mask.vlan_tag1);
+                               0 : cpu_to_be16(rule->tuples_mask.vlan_tag1);
        }
 
        if (fs->flow_type & FLOW_MAC_EXT) {
index fe3201b..9c6438d 100644 (file)
@@ -1905,10 +1905,9 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p)
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
 
-       if (adapter->state != VNIC_PROBED) {
-               ether_addr_copy(adapter->mac_addr, addr->sa_data);
+       ether_addr_copy(adapter->mac_addr, addr->sa_data);
+       if (adapter->state != VNIC_PROBED)
                rc = __ibmvnic_set_mac(netdev, addr->sa_data);
-       }
 
        return rc;
 }
@@ -5218,16 +5217,14 @@ static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset)
 {
        struct device *dev = &adapter->vdev->dev;
        unsigned long timeout = msecs_to_jiffies(20000);
-       u64 old_num_rx_queues, old_num_tx_queues;
+       u64 old_num_rx_queues = adapter->req_rx_queues;
+       u64 old_num_tx_queues = adapter->req_tx_queues;
        int rc;
 
        adapter->from_passive_init = false;
 
-       if (reset) {
-               old_num_rx_queues = adapter->req_rx_queues;
-               old_num_tx_queues = adapter->req_tx_queues;
+       if (reset)
                reinit_completion(&adapter->init_done);
-       }
 
        adapter->init_done_rc = 0;
        rc = ibmvnic_send_crq_init(adapter);
@@ -5410,9 +5407,9 @@ static void ibmvnic_remove(struct vio_dev *dev)
         * after setting state, so __ibmvnic_reset() which is called
         * from the flush_work() below, can make progress.
         */
-       spin_lock_irqsave(&adapter->rwi_lock, flags);
+       spin_lock(&adapter->rwi_lock);
        adapter->state = VNIC_REMOVING;
-       spin_unlock_irqrestore(&adapter->rwi_lock, flags);
+       spin_unlock(&adapter->rwi_lock);
 
        spin_unlock_irqrestore(&adapter->state_lock, flags);
 
index 0a867d6..dc5b3c0 100644 (file)
@@ -1776,7 +1776,8 @@ static int iavf_init_get_resources(struct iavf_adapter *adapter)
                goto err_alloc;
        }
 
-       if (iavf_process_config(adapter))
+       err = iavf_process_config(adapter);
+       if (err)
                goto err_alloc;
        adapter->current_op = VIRTCHNL_OP_UNKNOWN;
 
index eca7352..54d4726 100644 (file)
@@ -575,6 +575,11 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
                return -EINVAL;
        }
 
+       if (xs->props.mode != XFRM_MODE_TRANSPORT) {
+               netdev_err(dev, "Unsupported mode for ipsec offload\n");
+               return -EINVAL;
+       }
+
        if (ixgbe_ipsec_check_mgmt_ip(xs)) {
                netdev_err(dev, "IPsec IP addr clash with mgmt filters\n");
                return -EINVAL;
index fae8420..9f3f12e 100644 (file)
@@ -9565,8 +9565,10 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
        ixgbe_atr_compute_perfect_hash_82599(&input->filter, mask);
        err = ixgbe_fdir_write_perfect_filter_82599(hw, &input->filter,
                                                    input->sw_idx, queue);
-       if (!err)
-               ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
+       if (err)
+               goto err_out_w_lock;
+
+       ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
        spin_unlock(&adapter->fdir_perfect_lock);
 
        if ((uhtid != 0x800) && (adapter->jump_tables[uhtid]))
index 5170dd9..caaea2c 100644 (file)
@@ -272,6 +272,11 @@ static int ixgbevf_ipsec_add_sa(struct xfrm_state *xs)
                return -EINVAL;
        }
 
+       if (xs->props.mode != XFRM_MODE_TRANSPORT) {
+               netdev_err(dev, "Unsupported mode for ipsec offload\n");
+               return -EINVAL;
+       }
+
        if (xs->xso.flags & XFRM_OFFLOAD_INBOUND) {
                struct rx_sa rsa;
 
index 9caa375..68deae5 100644 (file)
@@ -56,7 +56,9 @@ static bool is_dev_rpm(void *cgxd)
 
 bool is_lmac_valid(struct cgx *cgx, int lmac_id)
 {
-       return cgx && test_bit(lmac_id, &cgx->lmac_bmap);
+       if (!cgx || lmac_id < 0 || lmac_id >= MAX_LMAC_PER_CGX)
+               return false;
+       return test_bit(lmac_id, &cgx->lmac_bmap);
 }
 
 struct mac_ops *get_mac_ops(void *cgxd)
index a8641a4..96d2891 100644 (file)
@@ -1225,8 +1225,6 @@ static int mtk_star_receive_packet(struct mtk_star_priv *priv)
                goto push_new_skb;
        }
 
-       desc_data.dma_addr = new_dma_addr;
-
        /* We can't fail anymore at this point: it's safe to unmap the skb. */
        mtk_star_dma_unmap_rx(priv, &desc_data);
 
@@ -1236,6 +1234,9 @@ static int mtk_star_receive_packet(struct mtk_star_priv *priv)
        desc_data.skb->dev = ndev;
        netif_receive_skb(desc_data.skb);
 
+       /* update dma_addr for new skb */
+       desc_data.dma_addr = new_dma_addr;
+
 push_new_skb:
        desc_data.len = skb_tailroom(new_skb);
        desc_data.skb = new_skb;
index 23849f2..1434df6 100644 (file)
@@ -47,7 +47,7 @@
 #define EN_ETHTOOL_SHORT_MASK cpu_to_be16(0xffff)
 #define EN_ETHTOOL_WORD_MASK  cpu_to_be32(0xffffffff)
 
-static int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
+int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
 {
        int i, t;
        int err = 0;
index 51b9700..5d0c9c6 100644 (file)
@@ -3554,6 +3554,8 @@ int mlx4_en_reset_config(struct net_device *dev,
                        en_err(priv, "Failed starting port\n");
        }
 
+       if (!err)
+               err = mlx4_en_moderation_update(priv);
 out:
        mutex_unlock(&mdev->state_lock);
        kfree(tmp);
index e8ed231..f3d1a20 100644 (file)
@@ -775,6 +775,7 @@ void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev);
 #define DEV_FEATURE_CHANGED(dev, new_features, feature) \
        ((dev->features & feature) ^ (new_features & feature))
 
+int mlx4_en_moderation_update(struct mlx4_en_priv *priv);
 int mlx4_en_reset_config(struct net_device *dev,
                         struct hwtstamp_config ts_config,
                         netdev_features_t new_features);
index 16e2df6..c4adc7f 100644 (file)
@@ -4430,6 +4430,7 @@ MLXSW_ITEM32(reg, ptys, ext_eth_proto_cap, 0x08, 0, 32);
 #define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4          BIT(20)
 #define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4          BIT(21)
 #define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4          BIT(22)
+#define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4      BIT(23)
 #define MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR            BIT(27)
 #define MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR            BIT(28)
 #define MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR            BIT(29)
index bd7f873..0bd6416 100644 (file)
@@ -1169,6 +1169,11 @@ static const struct mlxsw_sp1_port_link_mode mlxsw_sp1_port_link_mode[] = {
                .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
                .speed          = SPEED_100000,
        },
+       {
+               .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
+               .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
+               .speed          = SPEED_100000,
+       },
 };
 
 #define MLXSW_SP1_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp1_port_link_mode)
index 9ce9084..eda99d8 100644 (file)
@@ -5951,6 +5951,10 @@ mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
        if (mlxsw_sp->router->aborted)
                return 0;
 
+       if (fen_info->fi->nh &&
+           !mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, fen_info->fi->nh->id))
+               return 0;
+
        fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, fen_info->tb_id,
                                         &fen_info->dst, sizeof(fen_info->dst),
                                         fen_info->dst_len,
@@ -6601,6 +6605,9 @@ static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
        if (mlxsw_sp_fib6_rt_should_ignore(rt))
                return 0;
 
+       if (rt->nh && !mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, rt->nh->id))
+               return 0;
+
        fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->fib6_table->tb6_id,
                                         &rt->fib6_dst.addr,
                                         sizeof(rt->fib6_dst.addr),
index 40e2e79..131b2a5 100644 (file)
@@ -613,7 +613,8 @@ static const struct mlxsw_sx_port_link_mode mlxsw_sx_port_link_mode[] = {
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 |
                                  MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
-                                 MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4,
+                                 MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
+                                 MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
                .speed          = 100000,
        },
 };
index dbdfabf..1c3e204 100644 (file)
@@ -2040,7 +2040,7 @@ lan743x_rx_trim_skb(struct sk_buff *skb, int frame_length)
                dev_kfree_skb_irq(skb);
                return NULL;
        }
-       frame_length = max_t(int, 0, frame_length - RX_HEAD_PADDING - 2);
+       frame_length = max_t(int, 0, frame_length - RX_HEAD_PADDING - 4);
        if (skb->len > frame_length) {
                skb->tail -= skb->len - frame_length;
                skb->len = frame_length;
index c0ede0c..05cb040 100644 (file)
@@ -13,6 +13,7 @@ if NET_VENDOR_MICROSEMI
 
 # Users should depend on NET_SWITCHDEV, HAS_IOMEM
 config MSCC_OCELOT_SWITCH_LIB
+       select NET_DEVLINK
        select REGMAP_MMIO
        select PACKING
        select PHYLIB
index c3ac026..a41b458 100644 (file)
@@ -540,13 +540,14 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
                        return -EOPNOTSUPP;
                }
 
+               flow_rule_match_ipv4_addrs(rule, &match);
+
                if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) {
                        NL_SET_ERR_MSG_MOD(extack,
                                           "Key type S1_NORMAL cannot match on destination IP");
                        return -EOPNOTSUPP;
                }
 
-               flow_rule_match_ipv4_addrs(rule, &match);
                tmp = &filter->key.ipv4.sip.value.addr[0];
                memcpy(tmp, &match.key->src, 4);
 
index f704da3..7aad0ba 100644 (file)
@@ -767,7 +767,7 @@ static void r8168fp_adjust_ocp_cmd(struct rtl8169_private *tp, u32 *cmd, int typ
        if (type == ERIAR_OOB &&
            (tp->mac_version == RTL_GIGA_MAC_VER_52 ||
             tp->mac_version == RTL_GIGA_MAC_VER_53))
-               *cmd |= 0x7f0 << 18;
+               *cmd |= 0xf70 << 18;
 }
 
 DECLARE_RTL_COND(rtl_eriar_cond)
index 590b088..f029c7c 100644 (file)
@@ -560,6 +560,8 @@ static struct sh_eth_cpu_data r7s72100_data = {
                          EESR_TDE,
        .fdr_value      = 0x0000070f,
 
+       .trscer_err_mask = DESC_I_RINT8 | DESC_I_RINT5,
+
        .no_psr         = 1,
        .apr            = 1,
        .mpr            = 1,
@@ -780,6 +782,8 @@ static struct sh_eth_cpu_data r7s9210_data = {
 
        .fdr_value      = 0x0000070f,
 
+       .trscer_err_mask = DESC_I_RINT8 | DESC_I_RINT5,
+
        .apr            = 1,
        .mpr            = 1,
        .tpauser        = 1,
@@ -1089,6 +1093,9 @@ static struct sh_eth_cpu_data sh771x_data = {
                          EESIPR_CEEFIP | EESIPR_CELFIP |
                          EESIPR_RRFIP | EESIPR_RTLFIP | EESIPR_RTSFIP |
                          EESIPR_PREIP | EESIPR_CERFIP,
+
+       .trscer_err_mask = DESC_I_RINT8,
+
        .tsu            = 1,
        .dual_port      = 1,
 };
index 751dfde..0b64f77 100644 (file)
@@ -233,6 +233,7 @@ static void common_default_data(struct plat_stmmacenet_data *plat)
 static int intel_mgbe_common_data(struct pci_dev *pdev,
                                  struct plat_stmmacenet_data *plat)
 {
+       char clk_name[20];
        int ret;
        int i;
 
@@ -301,8 +302,10 @@ static int intel_mgbe_common_data(struct pci_dev *pdev,
        plat->eee_usecs_rate = plat->clk_ptp_rate;
 
        /* Set system clock */
+       sprintf(clk_name, "%s-%s", "stmmac", pci_name(pdev));
+
        plat->stmmac_clk = clk_register_fixed_rate(&pdev->dev,
-                                                  "stmmac-clk", NULL, 0,
+                                                  clk_name, NULL, 0,
                                                   plat->clk_ptp_rate);
 
        if (IS_ERR(plat->stmmac_clk)) {
@@ -446,8 +449,8 @@ static int tgl_common_data(struct pci_dev *pdev,
        return intel_mgbe_common_data(pdev, plat);
 }
 
-static int tgl_sgmii_data(struct pci_dev *pdev,
-                         struct plat_stmmacenet_data *plat)
+static int tgl_sgmii_phy0_data(struct pci_dev *pdev,
+                              struct plat_stmmacenet_data *plat)
 {
        plat->bus_id = 1;
        plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
@@ -456,12 +459,26 @@ static int tgl_sgmii_data(struct pci_dev *pdev,
        return tgl_common_data(pdev, plat);
 }
 
-static struct stmmac_pci_info tgl_sgmii1g_info = {
-       .setup = tgl_sgmii_data,
+static struct stmmac_pci_info tgl_sgmii1g_phy0_info = {
+       .setup = tgl_sgmii_phy0_data,
 };
 
-static int adls_sgmii_data(struct pci_dev *pdev,
-                          struct plat_stmmacenet_data *plat)
+static int tgl_sgmii_phy1_data(struct pci_dev *pdev,
+                              struct plat_stmmacenet_data *plat)
+{
+       plat->bus_id = 2;
+       plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+       plat->serdes_powerup = intel_serdes_powerup;
+       plat->serdes_powerdown = intel_serdes_powerdown;
+       return tgl_common_data(pdev, plat);
+}
+
+static struct stmmac_pci_info tgl_sgmii1g_phy1_info = {
+       .setup = tgl_sgmii_phy1_data,
+};
+
+static int adls_sgmii_phy0_data(struct pci_dev *pdev,
+                               struct plat_stmmacenet_data *plat)
 {
        plat->bus_id = 1;
        plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
@@ -471,10 +488,24 @@ static int adls_sgmii_data(struct pci_dev *pdev,
        return tgl_common_data(pdev, plat);
 }
 
-static struct stmmac_pci_info adls_sgmii1g_info = {
-       .setup = adls_sgmii_data,
+static struct stmmac_pci_info adls_sgmii1g_phy0_info = {
+       .setup = adls_sgmii_phy0_data,
 };
 
+static int adls_sgmii_phy1_data(struct pci_dev *pdev,
+                               struct plat_stmmacenet_data *plat)
+{
+       plat->bus_id = 2;
+       plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+
+       /* SerDes power up and power down are done in BIOS for ADL */
+
+       return tgl_common_data(pdev, plat);
+}
+
+static struct stmmac_pci_info adls_sgmii1g_phy1_info = {
+       .setup = adls_sgmii_phy1_data,
+};
 static const struct stmmac_pci_func_data galileo_stmmac_func_data[] = {
        {
                .func = 6,
@@ -756,11 +787,11 @@ static const struct pci_device_id intel_eth_pci_id_table[] = {
        { PCI_DEVICE_DATA(INTEL, EHL_PSE1_RGMII1G_ID, &ehl_pse1_rgmii1g_info) },
        { PCI_DEVICE_DATA(INTEL, EHL_PSE1_SGMII1G_ID, &ehl_pse1_sgmii1g_info) },
        { PCI_DEVICE_DATA(INTEL, EHL_PSE1_SGMII2G5_ID, &ehl_pse1_sgmii1g_info) },
-       { PCI_DEVICE_DATA(INTEL, TGL_SGMII1G_ID, &tgl_sgmii1g_info) },
-       { PCI_DEVICE_DATA(INTEL, TGLH_SGMII1G_0_ID, &tgl_sgmii1g_info) },
-       { PCI_DEVICE_DATA(INTEL, TGLH_SGMII1G_1_ID, &tgl_sgmii1g_info) },
-       { PCI_DEVICE_DATA(INTEL, ADLS_SGMII1G_0_ID, &adls_sgmii1g_info) },
-       { PCI_DEVICE_DATA(INTEL, ADLS_SGMII1G_1_ID, &adls_sgmii1g_info) },
+       { PCI_DEVICE_DATA(INTEL, TGL_SGMII1G_ID, &tgl_sgmii1g_phy0_info) },
+       { PCI_DEVICE_DATA(INTEL, TGLH_SGMII1G_0_ID, &tgl_sgmii1g_phy0_info) },
+       { PCI_DEVICE_DATA(INTEL, TGLH_SGMII1G_1_ID, &tgl_sgmii1g_phy1_info) },
+       { PCI_DEVICE_DATA(INTEL, ADLS_SGMII1G_0_ID, &adls_sgmii1g_phy0_info) },
+       { PCI_DEVICE_DATA(INTEL, ADLS_SGMII1G_1_ID, &adls_sgmii1g_phy1_info) },
        {}
 };
 MODULE_DEVICE_TABLE(pci, intel_eth_pci_id_table);
index c6540b0..cbf4429 100644 (file)
@@ -402,19 +402,53 @@ static void dwmac4_rd_set_tx_ic(struct dma_desc *p)
        p->des2 |= cpu_to_le32(TDES2_INTERRUPT_ON_COMPLETION);
 }
 
-static void dwmac4_display_ring(void *head, unsigned int size, bool rx)
+static void dwmac4_display_ring(void *head, unsigned int size, bool rx,
+                               dma_addr_t dma_rx_phy, unsigned int desc_size)
 {
-       struct dma_desc *p = (struct dma_desc *)head;
+       dma_addr_t dma_addr;
        int i;
 
        pr_info("%s descriptor ring:\n", rx ? "RX" : "TX");
 
-       for (i = 0; i < size; i++) {
-               pr_info("%03d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
-                       i, (unsigned int)virt_to_phys(p),
-                       le32_to_cpu(p->des0), le32_to_cpu(p->des1),
-                       le32_to_cpu(p->des2), le32_to_cpu(p->des3));
-               p++;
+       if (desc_size == sizeof(struct dma_desc)) {
+               struct dma_desc *p = (struct dma_desc *)head;
+
+               for (i = 0; i < size; i++) {
+                       dma_addr = dma_rx_phy + i * sizeof(*p);
+                       pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x\n",
+                               i, &dma_addr,
+                               le32_to_cpu(p->des0), le32_to_cpu(p->des1),
+                               le32_to_cpu(p->des2), le32_to_cpu(p->des3));
+                       p++;
+               }
+       } else if (desc_size == sizeof(struct dma_extended_desc)) {
+               struct dma_extended_desc *extp = (struct dma_extended_desc *)head;
+
+               for (i = 0; i < size; i++) {
+                       dma_addr = dma_rx_phy + i * sizeof(*extp);
+                       pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+                               i, &dma_addr,
+                               le32_to_cpu(extp->basic.des0), le32_to_cpu(extp->basic.des1),
+                               le32_to_cpu(extp->basic.des2), le32_to_cpu(extp->basic.des3),
+                               le32_to_cpu(extp->des4), le32_to_cpu(extp->des5),
+                               le32_to_cpu(extp->des6), le32_to_cpu(extp->des7));
+                       extp++;
+               }
+       } else if (desc_size == sizeof(struct dma_edesc)) {
+               struct dma_edesc *ep = (struct dma_edesc *)head;
+
+               for (i = 0; i < size; i++) {
+                       dma_addr = dma_rx_phy + i * sizeof(*ep);
+                       pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+                               i, &dma_addr,
+                               le32_to_cpu(ep->des4), le32_to_cpu(ep->des5),
+                               le32_to_cpu(ep->des6), le32_to_cpu(ep->des7),
+                               le32_to_cpu(ep->basic.des0), le32_to_cpu(ep->basic.des1),
+                               le32_to_cpu(ep->basic.des2), le32_to_cpu(ep->basic.des3));
+                       ep++;
+               }
+       } else {
+               pr_err("unsupported descriptor!");
        }
 }
 
@@ -499,10 +533,15 @@ static void dwmac4_get_rx_header_len(struct dma_desc *p, unsigned int *len)
        *len = le32_to_cpu(p->des2) & RDES2_HL;
 }
 
-static void dwmac4_set_sec_addr(struct dma_desc *p, dma_addr_t addr)
+static void dwmac4_set_sec_addr(struct dma_desc *p, dma_addr_t addr, bool buf2_valid)
 {
        p->des2 = cpu_to_le32(lower_32_bits(addr));
-       p->des3 = cpu_to_le32(upper_32_bits(addr) | RDES3_BUFFER2_VALID_ADDR);
+       p->des3 = cpu_to_le32(upper_32_bits(addr));
+
+       if (buf2_valid)
+               p->des3 |= cpu_to_le32(RDES3_BUFFER2_VALID_ADDR);
+       else
+               p->des3 &= cpu_to_le32(~RDES3_BUFFER2_VALID_ADDR);
 }
 
 static void dwmac4_set_tbs(struct dma_edesc *p, u32 sec, u32 nsec)
index bb29bfc..62aa0e9 100644 (file)
@@ -124,6 +124,23 @@ static void dwmac4_dma_init_channel(void __iomem *ioaddr,
               ioaddr + DMA_CHAN_INTR_ENA(chan));
 }
 
+static void dwmac410_dma_init_channel(void __iomem *ioaddr,
+                                     struct stmmac_dma_cfg *dma_cfg, u32 chan)
+{
+       u32 value;
+
+       /* common channel control register config */
+       value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
+       if (dma_cfg->pblx8)
+               value = value | DMA_BUS_MODE_PBL;
+
+       writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
+
+       /* Mask interrupts by writing to CSR7 */
+       writel(DMA_CHAN_INTR_DEFAULT_MASK_4_10,
+              ioaddr + DMA_CHAN_INTR_ENA(chan));
+}
+
 static void dwmac4_dma_init(void __iomem *ioaddr,
                            struct stmmac_dma_cfg *dma_cfg, int atds)
 {
@@ -523,7 +540,7 @@ const struct stmmac_dma_ops dwmac4_dma_ops = {
 const struct stmmac_dma_ops dwmac410_dma_ops = {
        .reset = dwmac4_dma_reset,
        .init = dwmac4_dma_init,
-       .init_chan = dwmac4_dma_init_channel,
+       .init_chan = dwmac410_dma_init_channel,
        .init_rx_chan = dwmac4_dma_init_rx_chan,
        .init_tx_chan = dwmac4_dma_init_tx_chan,
        .axi = dwmac4_dma_axi,
index 0b4ee2d..71e5075 100644 (file)
@@ -53,10 +53,6 @@ void dwmac4_dma_stop_tx(void __iomem *ioaddr, u32 chan)
 
        value &= ~DMA_CONTROL_ST;
        writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan));
-
-       value = readl(ioaddr + GMAC_CONFIG);
-       value &= ~GMAC_CONFIG_TE;
-       writel(value, ioaddr + GMAC_CONFIG);
 }
 
 void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan)
index 0aaf19a..ccfb010 100644 (file)
@@ -292,7 +292,7 @@ static void dwxgmac2_get_rx_header_len(struct dma_desc *p, unsigned int *len)
                *len = le32_to_cpu(p->des2) & XGMAC_RDES2_HL;
 }
 
-static void dwxgmac2_set_sec_addr(struct dma_desc *p, dma_addr_t addr)
+static void dwxgmac2_set_sec_addr(struct dma_desc *p, dma_addr_t addr, bool is_valid)
 {
        p->des2 = cpu_to_le32(lower_32_bits(addr));
        p->des3 = cpu_to_le32(upper_32_bits(addr));
index d02cec2..6650edf 100644 (file)
@@ -417,19 +417,22 @@ static int enh_desc_get_rx_timestamp_status(void *desc, void *next_desc,
        }
 }
 
-static void enh_desc_display_ring(void *head, unsigned int size, bool rx)
+static void enh_desc_display_ring(void *head, unsigned int size, bool rx,
+                                 dma_addr_t dma_rx_phy, unsigned int desc_size)
 {
        struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
+       dma_addr_t dma_addr;
        int i;
 
        pr_info("Extended %s descriptor ring:\n", rx ? "RX" : "TX");
 
        for (i = 0; i < size; i++) {
                u64 x;
+               dma_addr = dma_rx_phy + i * sizeof(*ep);
 
                x = *(u64 *)ep;
-               pr_info("%03d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
-                       i, (unsigned int)virt_to_phys(ep),
+               pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x\n",
+                       i, &dma_addr,
                        (unsigned int)x, (unsigned int)(x >> 32),
                        ep->basic.des2, ep->basic.des3);
                ep++;
index b40b2e0..979ac9f 100644 (file)
@@ -78,7 +78,8 @@ struct stmmac_desc_ops {
        /* get rx timestamp status */
        int (*get_rx_timestamp_status)(void *desc, void *next_desc, u32 ats);
        /* Display ring */
-       void (*display_ring)(void *head, unsigned int size, bool rx);
+       void (*display_ring)(void *head, unsigned int size, bool rx,
+                            dma_addr_t dma_rx_phy, unsigned int desc_size);
        /* set MSS via context descriptor */
        void (*set_mss)(struct dma_desc *p, unsigned int mss);
        /* get descriptor skbuff address */
@@ -91,7 +92,7 @@ struct stmmac_desc_ops {
        int (*get_rx_hash)(struct dma_desc *p, u32 *hash,
                           enum pkt_hash_types *type);
        void (*get_rx_header_len)(struct dma_desc *p, unsigned int *len);
-       void (*set_sec_addr)(struct dma_desc *p, dma_addr_t addr);
+       void (*set_sec_addr)(struct dma_desc *p, dma_addr_t addr, bool buf2_valid);
        void (*set_sarc)(struct dma_desc *p, u32 sarc_type);
        void (*set_vlan_tag)(struct dma_desc *p, u16 tag, u16 inner_tag,
                             u32 inner_type);
index f083360..98ef43f 100644 (file)
@@ -269,19 +269,22 @@ static int ndesc_get_rx_timestamp_status(void *desc, void *next_desc, u32 ats)
                return 1;
 }
 
-static void ndesc_display_ring(void *head, unsigned int size, bool rx)
+static void ndesc_display_ring(void *head, unsigned int size, bool rx,
+                              dma_addr_t dma_rx_phy, unsigned int desc_size)
 {
        struct dma_desc *p = (struct dma_desc *)head;
+       dma_addr_t dma_addr;
        int i;
 
        pr_info("%s descriptor ring:\n", rx ? "RX" : "TX");
 
        for (i = 0; i < size; i++) {
                u64 x;
+               dma_addr = dma_rx_phy + i * sizeof(*p);
 
                x = *(u64 *)p;
-               pr_info("%03d [0x%x]: 0x%x 0x%x 0x%x 0x%x",
-                       i, (unsigned int)virt_to_phys(p),
+               pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x",
+                       i, &dma_addr,
                        (unsigned int)x, (unsigned int)(x >> 32),
                        p->des2, p->des3);
                p++;
index 26b971c..208cae3 100644 (file)
@@ -1133,6 +1133,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 static void stmmac_display_rx_rings(struct stmmac_priv *priv)
 {
        u32 rx_cnt = priv->plat->rx_queues_to_use;
+       unsigned int desc_size;
        void *head_rx;
        u32 queue;
 
@@ -1142,19 +1143,24 @@ static void stmmac_display_rx_rings(struct stmmac_priv *priv)
 
                pr_info("\tRX Queue %u rings\n", queue);
 
-               if (priv->extend_desc)
+               if (priv->extend_desc) {
                        head_rx = (void *)rx_q->dma_erx;
-               else
+                       desc_size = sizeof(struct dma_extended_desc);
+               } else {
                        head_rx = (void *)rx_q->dma_rx;
+                       desc_size = sizeof(struct dma_desc);
+               }
 
                /* Display RX ring */
-               stmmac_display_ring(priv, head_rx, priv->dma_rx_size, true);
+               stmmac_display_ring(priv, head_rx, priv->dma_rx_size, true,
+                                   rx_q->dma_rx_phy, desc_size);
        }
 }
 
 static void stmmac_display_tx_rings(struct stmmac_priv *priv)
 {
        u32 tx_cnt = priv->plat->tx_queues_to_use;
+       unsigned int desc_size;
        void *head_tx;
        u32 queue;
 
@@ -1164,14 +1170,19 @@ static void stmmac_display_tx_rings(struct stmmac_priv *priv)
 
                pr_info("\tTX Queue %d rings\n", queue);
 
-               if (priv->extend_desc)
+               if (priv->extend_desc) {
                        head_tx = (void *)tx_q->dma_etx;
-               else if (tx_q->tbs & STMMAC_TBS_AVAIL)
+                       desc_size = sizeof(struct dma_extended_desc);
+               } else if (tx_q->tbs & STMMAC_TBS_AVAIL) {
                        head_tx = (void *)tx_q->dma_entx;
-               else
+                       desc_size = sizeof(struct dma_edesc);
+               } else {
                        head_tx = (void *)tx_q->dma_tx;
+                       desc_size = sizeof(struct dma_desc);
+               }
 
-               stmmac_display_ring(priv, head_tx, priv->dma_tx_size, false);
+               stmmac_display_ring(priv, head_tx, priv->dma_tx_size, false,
+                                   tx_q->dma_tx_phy, desc_size);
        }
 }
 
@@ -1303,9 +1314,10 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
                        return -ENOMEM;
 
                buf->sec_addr = page_pool_get_dma_addr(buf->sec_page);
-               stmmac_set_desc_sec_addr(priv, p, buf->sec_addr);
+               stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, true);
        } else {
                buf->sec_page = NULL;
+               stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, false);
        }
 
        buf->addr = page_pool_get_dma_addr(buf->page);
@@ -1367,6 +1379,88 @@ static void stmmac_free_tx_buffer(struct stmmac_priv *priv, u32 queue, int i)
        }
 }
 
+/**
+ * stmmac_reinit_rx_buffers - reinit the RX descriptor buffer.
+ * @priv: driver private structure
+ * Description: this function is called to re-allocate a receive buffer, perform
+ * the DMA mapping and init the descriptor.
+ */
+static void stmmac_reinit_rx_buffers(struct stmmac_priv *priv)
+{
+       u32 rx_count = priv->plat->rx_queues_to_use;
+       u32 queue;
+       int i;
+
+       for (queue = 0; queue < rx_count; queue++) {
+               struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+
+               for (i = 0; i < priv->dma_rx_size; i++) {
+                       struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
+
+                       if (buf->page) {
+                               page_pool_recycle_direct(rx_q->page_pool, buf->page);
+                               buf->page = NULL;
+                       }
+
+                       if (priv->sph && buf->sec_page) {
+                               page_pool_recycle_direct(rx_q->page_pool, buf->sec_page);
+                               buf->sec_page = NULL;
+                       }
+               }
+       }
+
+       for (queue = 0; queue < rx_count; queue++) {
+               struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+
+               for (i = 0; i < priv->dma_rx_size; i++) {
+                       struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
+                       struct dma_desc *p;
+
+                       if (priv->extend_desc)
+                               p = &((rx_q->dma_erx + i)->basic);
+                       else
+                               p = rx_q->dma_rx + i;
+
+                       if (!buf->page) {
+                               buf->page = page_pool_dev_alloc_pages(rx_q->page_pool);
+                               if (!buf->page)
+                                       goto err_reinit_rx_buffers;
+
+                               buf->addr = page_pool_get_dma_addr(buf->page);
+                       }
+
+                       if (priv->sph && !buf->sec_page) {
+                               buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool);
+                               if (!buf->sec_page)
+                                       goto err_reinit_rx_buffers;
+
+                               buf->sec_addr = page_pool_get_dma_addr(buf->sec_page);
+                       }
+
+                       stmmac_set_desc_addr(priv, p, buf->addr);
+                       if (priv->sph)
+                               stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, true);
+                       else
+                               stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, false);
+                       if (priv->dma_buf_sz == BUF_SIZE_16KiB)
+                               stmmac_init_desc3(priv, p);
+               }
+       }
+
+       return;
+
+err_reinit_rx_buffers:
+       do {
+               while (--i >= 0)
+                       stmmac_free_rx_buffer(priv, queue, i);
+
+               if (queue == 0)
+                       break;
+
+               i = priv->dma_rx_size;
+       } while (queue-- > 0);
+}
+
 /**
  * init_dma_rx_desc_rings - init the RX descriptor rings
  * @dev: net device structure
@@ -3648,7 +3742,10 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
                                           DMA_FROM_DEVICE);
 
                stmmac_set_desc_addr(priv, p, buf->addr);
-               stmmac_set_desc_sec_addr(priv, p, buf->sec_addr);
+               if (priv->sph)
+                       stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, true);
+               else
+                       stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, false);
                stmmac_refill_desc3(priv, rx_q, p);
 
                rx_q->rx_count_frames++;
@@ -3736,18 +3833,23 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
        unsigned int count = 0, error = 0, len = 0;
        int status = 0, coe = priv->hw->rx_csum;
        unsigned int next_entry = rx_q->cur_rx;
+       unsigned int desc_size;
        struct sk_buff *skb = NULL;
 
        if (netif_msg_rx_status(priv)) {
                void *rx_head;
 
                netdev_dbg(priv->dev, "%s: descriptor ring:\n", __func__);
-               if (priv->extend_desc)
+               if (priv->extend_desc) {
                        rx_head = (void *)rx_q->dma_erx;
-               else
+                       desc_size = sizeof(struct dma_extended_desc);
+               } else {
                        rx_head = (void *)rx_q->dma_rx;
+                       desc_size = sizeof(struct dma_desc);
+               }
 
-               stmmac_display_ring(priv, rx_head, priv->dma_rx_size, true);
+               stmmac_display_ring(priv, rx_head, priv->dma_rx_size, true,
+                                   rx_q->dma_rx_phy, desc_size);
        }
        while (count < limit) {
                unsigned int buf1_len = 0, buf2_len = 0;
@@ -4315,24 +4417,27 @@ static int stmmac_set_mac_address(struct net_device *ndev, void *addr)
 static struct dentry *stmmac_fs_dir;
 
 static void sysfs_display_ring(void *head, int size, int extend_desc,
-                              struct seq_file *seq)
+                              struct seq_file *seq, dma_addr_t dma_phy_addr)
 {
        int i;
        struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
        struct dma_desc *p = (struct dma_desc *)head;
+       dma_addr_t dma_addr;
 
        for (i = 0; i < size; i++) {
                if (extend_desc) {
-                       seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
-                                  i, (unsigned int)virt_to_phys(ep),
+                       dma_addr = dma_phy_addr + i * sizeof(*ep);
+                       seq_printf(seq, "%d [%pad]: 0x%x 0x%x 0x%x 0x%x\n",
+                                  i, &dma_addr,
                                   le32_to_cpu(ep->basic.des0),
                                   le32_to_cpu(ep->basic.des1),
                                   le32_to_cpu(ep->basic.des2),
                                   le32_to_cpu(ep->basic.des3));
                        ep++;
                } else {
-                       seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
-                                  i, (unsigned int)virt_to_phys(p),
+                       dma_addr = dma_phy_addr + i * sizeof(*p);
+                       seq_printf(seq, "%d [%pad]: 0x%x 0x%x 0x%x 0x%x\n",
+                                  i, &dma_addr,
                                   le32_to_cpu(p->des0), le32_to_cpu(p->des1),
                                   le32_to_cpu(p->des2), le32_to_cpu(p->des3));
                        p++;
@@ -4360,11 +4465,11 @@ static int stmmac_rings_status_show(struct seq_file *seq, void *v)
                if (priv->extend_desc) {
                        seq_printf(seq, "Extended descriptor ring:\n");
                        sysfs_display_ring((void *)rx_q->dma_erx,
-                                          priv->dma_rx_size, 1, seq);
+                                          priv->dma_rx_size, 1, seq, rx_q->dma_rx_phy);
                } else {
                        seq_printf(seq, "Descriptor ring:\n");
                        sysfs_display_ring((void *)rx_q->dma_rx,
-                                          priv->dma_rx_size, 0, seq);
+                                          priv->dma_rx_size, 0, seq, rx_q->dma_rx_phy);
                }
        }
 
@@ -4376,11 +4481,11 @@ static int stmmac_rings_status_show(struct seq_file *seq, void *v)
                if (priv->extend_desc) {
                        seq_printf(seq, "Extended descriptor ring:\n");
                        sysfs_display_ring((void *)tx_q->dma_etx,
-                                          priv->dma_tx_size, 1, seq);
+                                          priv->dma_tx_size, 1, seq, tx_q->dma_tx_phy);
                } else if (!(tx_q->tbs & STMMAC_TBS_AVAIL)) {
                        seq_printf(seq, "Descriptor ring:\n");
                        sysfs_display_ring((void *)tx_q->dma_tx,
-                                          priv->dma_tx_size, 0, seq);
+                                          priv->dma_tx_size, 0, seq, tx_q->dma_tx_phy);
                }
        }
 
@@ -5144,13 +5249,16 @@ int stmmac_dvr_remove(struct device *dev)
        netdev_info(priv->dev, "%s: removing driver", __func__);
 
        stmmac_stop_all_dma(priv);
+       stmmac_mac_set(priv, priv->ioaddr, false);
+       netif_carrier_off(ndev);
+       unregister_netdev(ndev);
 
+       /* Serdes power down needs to happen after VLAN filter
+        * is deleted that is triggered by unregister_netdev().
+        */
        if (priv->plat->serdes_powerdown)
                priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv);
 
-       stmmac_mac_set(priv, priv->ioaddr, false);
-       netif_carrier_off(ndev);
-       unregister_netdev(ndev);
 #ifdef CONFIG_DEBUG_FS
        stmmac_exit_fs(ndev);
 #endif
@@ -5257,6 +5365,8 @@ static void stmmac_reset_queues_param(struct stmmac_priv *priv)
                tx_q->cur_tx = 0;
                tx_q->dirty_tx = 0;
                tx_q->mss = 0;
+
+               netdev_tx_reset_queue(netdev_get_tx_queue(priv->dev, queue));
        }
 }
 
@@ -5318,7 +5428,7 @@ int stmmac_resume(struct device *dev)
        mutex_lock(&priv->lock);
 
        stmmac_reset_queues_param(priv);
-
+       stmmac_reinit_rx_buffers(priv);
        stmmac_free_tx_skbufs(priv);
        stmmac_clear_descriptors(priv);
 
index 68695d4..707ccdd 100644 (file)
@@ -3931,8 +3931,6 @@ static void niu_xmac_interrupt(struct niu *np)
                mp->rx_mcasts += RXMAC_MC_FRM_CNT_COUNT;
        if (val & XRXMAC_STATUS_RXBCAST_CNT_EXP)
                mp->rx_bcasts += RXMAC_BC_FRM_CNT_COUNT;
-       if (val & XRXMAC_STATUS_RXBCAST_CNT_EXP)
-               mp->rx_bcasts += RXMAC_BC_FRM_CNT_COUNT;
        if (val & XRXMAC_STATUS_RXHIST1_CNT_EXP)
                mp->rx_hist_cnt1 += RXMAC_HIST_CNT1_COUNT;
        if (val & XRXMAC_STATUS_RXHIST2_CNT_EXP)
index b8f4f41..d054c6e 100644 (file)
@@ -2044,6 +2044,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                /*bdx_hw_reset(priv); */
                if (bdx_read_mac(priv)) {
                        pr_err("load MAC address failed\n");
+                       err = -EFAULT;
                        goto err_out_iomap;
                }
                SET_NETDEV_DEV(ndev, &pdev->dev);
index 71d6629..9f5b561 100644 (file)
@@ -171,11 +171,6 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
                goto out_drop;
        }
 
-       if (len > sp->mtu) {    /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
-               msg = "oversized transmit packet!";
-               goto out_drop;
-       }
-
        if (p[0] > 5) {
                msg = "invalid KISS command";
                goto out_drop;
index e1a497d..59ac04a 100644 (file)
@@ -229,7 +229,7 @@ int netvsc_send(struct net_device *net,
                bool xdp_tx);
 void netvsc_linkstatus_callback(struct net_device *net,
                                struct rndis_message *resp,
-                               void *data);
+                               void *data, u32 data_buflen);
 int netvsc_recv_callback(struct net_device *net,
                         struct netvsc_device *nvdev,
                         struct netvsc_channel *nvchan);
index 8176fa0..15f262b 100644 (file)
@@ -744,7 +744,7 @@ static netdev_tx_t netvsc_start_xmit(struct sk_buff *skb,
  */
 void netvsc_linkstatus_callback(struct net_device *net,
                                struct rndis_message *resp,
-                               void *data)
+                               void *data, u32 data_buflen)
 {
        struct rndis_indicate_status *indicate = &resp->msg.indicate_status;
        struct net_device_context *ndev_ctx = netdev_priv(net);
@@ -765,11 +765,16 @@ void netvsc_linkstatus_callback(struct net_device *net,
        if (indicate->status == RNDIS_STATUS_LINK_SPEED_CHANGE) {
                u32 speed;
 
-               /* Validate status_buf_offset */
+               /* Validate status_buf_offset and status_buflen.
+                *
+                * Certain (pre-Fe) implementations of Hyper-V's vSwitch didn't account
+                * for the status buffer field in resp->msg_len; perform the validation
+                * using data_buflen (>= resp->msg_len).
+                */
                if (indicate->status_buflen < sizeof(speed) ||
                    indicate->status_buf_offset < sizeof(*indicate) ||
-                   resp->msg_len - RNDIS_HEADER_SIZE < indicate->status_buf_offset ||
-                   resp->msg_len - RNDIS_HEADER_SIZE - indicate->status_buf_offset
+                   data_buflen - RNDIS_HEADER_SIZE < indicate->status_buf_offset ||
+                   data_buflen - RNDIS_HEADER_SIZE - indicate->status_buf_offset
                                < indicate->status_buflen) {
                        netdev_err(net, "invalid rndis_indicate_status packet\n");
                        return;
index 123cc9d..c0e89e1 100644 (file)
@@ -620,7 +620,7 @@ int rndis_filter_receive(struct net_device *ndev,
 
        case RNDIS_MSG_INDICATE:
                /* notification msgs */
-               netvsc_linkstatus_callback(ndev, rndis_msg, data);
+               netvsc_linkstatus_callback(ndev, rndis_msg, data, buflen);
                break;
        default:
                netdev_err(ndev,
index aec9244..659d3dc 100644 (file)
@@ -294,6 +294,7 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
        dev_net_set(dev, nsim_dev_net(nsim_dev));
        ns = netdev_priv(dev);
        ns->netdev = dev;
+       u64_stats_init(&ns->syncp);
        ns->nsim_dev = nsim_dev;
        ns->nsim_dev_port = nsim_dev_port;
        ns->nsim_bus_dev = nsim_dev->nsim_bus_dev;
index be1224b..f7a2ec1 100644 (file)
@@ -290,6 +290,7 @@ static int dp83822_config_intr(struct phy_device *phydev)
 
 static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev)
 {
+       bool trigger_machine = false;
        int irq_status;
 
        /* The MISR1 and MISR2 registers are holding the interrupt status in
@@ -305,7 +306,7 @@ static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev)
                return IRQ_NONE;
        }
        if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
-               goto trigger_machine;
+               trigger_machine = true;
 
        irq_status = phy_read(phydev, MII_DP83822_MISR2);
        if (irq_status < 0) {
@@ -313,11 +314,11 @@ static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev)
                return IRQ_NONE;
        }
        if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
-               goto trigger_machine;
+               trigger_machine = true;
 
-       return IRQ_NONE;
+       if (!trigger_machine)
+               return IRQ_NONE;
 
-trigger_machine:
        phy_trigger_machine(phydev);
 
        return IRQ_HANDLED;
index 688fadf..7ea32fb 100644 (file)
@@ -264,6 +264,7 @@ static int dp83811_config_intr(struct phy_device *phydev)
 
 static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)
 {
+       bool trigger_machine = false;
        int irq_status;
 
        /* The INT_STAT registers 1, 2 and 3 are holding the interrupt status
@@ -279,7 +280,7 @@ static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)
                return IRQ_NONE;
        }
        if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
-               goto trigger_machine;
+               trigger_machine = true;
 
        irq_status = phy_read(phydev, MII_DP83811_INT_STAT2);
        if (irq_status < 0) {
@@ -287,7 +288,7 @@ static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)
                return IRQ_NONE;
        }
        if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
-               goto trigger_machine;
+               trigger_machine = true;
 
        irq_status = phy_read(phydev, MII_DP83811_INT_STAT3);
        if (irq_status < 0) {
@@ -295,11 +296,11 @@ static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)
                return IRQ_NONE;
        }
        if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
-               goto trigger_machine;
+               trigger_machine = true;
 
-       return IRQ_NONE;
+       if (!trigger_machine)
+               return IRQ_NONE;
 
-trigger_machine:
        phy_trigger_machine(phydev);
 
        return IRQ_HANDLED;
index 1be07e4..fc2e7cb 100644 (file)
@@ -276,14 +276,16 @@ int phy_ethtool_ksettings_set(struct phy_device *phydev,
 
        phydev->autoneg = autoneg;
 
-       phydev->speed = speed;
+       if (autoneg == AUTONEG_DISABLE) {
+               phydev->speed = speed;
+               phydev->duplex = duplex;
+       }
 
        linkmode_copy(phydev->advertising, advertising);
 
        linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
                         phydev->advertising, autoneg == AUTONEG_ENABLE);
 
-       phydev->duplex = duplex;
        phydev->master_slave_set = cmd->base.master_slave_cfg;
        phydev->mdix_ctrl = cmd->base.eth_tp_mdix_ctrl;
 
index ce49547..cc38e32 100644 (file)
@@ -230,7 +230,6 @@ static struct phy_driver genphy_driver;
 static LIST_HEAD(phy_fixup_list);
 static DEFINE_MUTEX(phy_fixup_lock);
 
-#ifdef CONFIG_PM
 static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
 {
        struct device_driver *drv = phydev->mdio.dev.driver;
@@ -270,7 +269,7 @@ out:
        return !phydev->suspended;
 }
 
-static int mdio_bus_phy_suspend(struct device *dev)
+static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
 {
        struct phy_device *phydev = to_phy_device(dev);
 
@@ -290,7 +289,7 @@ static int mdio_bus_phy_suspend(struct device *dev)
        return phy_suspend(phydev);
 }
 
-static int mdio_bus_phy_resume(struct device *dev)
+static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
 {
        struct phy_device *phydev = to_phy_device(dev);
        int ret;
@@ -316,7 +315,6 @@ no_resume:
 
 static SIMPLE_DEV_PM_OPS(mdio_bus_phy_pm_ops, mdio_bus_phy_suspend,
                         mdio_bus_phy_resume);
-#endif /* CONFIG_PM */
 
 /**
  * phy_register_fixup - creates a new phy_fixup and adds it to the list
index 4087c9e..8acf301 100644 (file)
@@ -851,17 +851,17 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
 
        /* check if we got everything */
        if (!ctx->data) {
-               dev_dbg(&intf->dev, "CDC Union missing and no IAD found\n");
+               dev_err(&intf->dev, "CDC Union missing and no IAD found\n");
                goto error;
        }
        if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) {
                if (!ctx->mbim_desc) {
-                       dev_dbg(&intf->dev, "MBIM functional descriptor missing\n");
+                       dev_err(&intf->dev, "MBIM functional descriptor missing\n");
                        goto error;
                }
        } else {
                if (!ctx->ether_desc || !ctx->func_desc) {
-                       dev_dbg(&intf->dev, "NCM or ECM functional descriptors missing\n");
+                       dev_err(&intf->dev, "NCM or ECM functional descriptors missing\n");
                        goto error;
                }
        }
@@ -870,7 +870,7 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
        if (ctx->data != ctx->control) {
                temp = usb_driver_claim_interface(driver, ctx->data, dev);
                if (temp) {
-                       dev_dbg(&intf->dev, "failed to claim data intf\n");
+                       dev_err(&intf->dev, "failed to claim data intf\n");
                        goto error;
                }
        }
@@ -926,7 +926,7 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
        if (ctx->ether_desc) {
                temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
                if (temp) {
-                       dev_dbg(&intf->dev, "failed to get mac address\n");
+                       dev_err(&intf->dev, "failed to get mac address\n");
                        goto error2;
                }
                dev_info(&intf->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
index 17a0505..6700f19 100644 (file)
@@ -429,13 +429,6 @@ static ssize_t add_mux_store(struct device *d,  struct device_attribute *attr, c
                goto err;
        }
 
-       /* we don't want to modify a running netdev */
-       if (netif_running(dev->net)) {
-               netdev_err(dev->net, "Cannot change a running device\n");
-               ret = -EBUSY;
-               goto err;
-       }
-
        ret = qmimux_register_device(dev->net, mux_id);
        if (!ret) {
                info->flags |= QMI_WWAN_FLAG_MUX;
@@ -465,13 +458,6 @@ static ssize_t del_mux_store(struct device *d,  struct device_attribute *attr, c
        if (!rtnl_trylock())
                return restart_syscall();
 
-       /* we don't want to modify a running netdev */
-       if (netif_running(dev->net)) {
-               netdev_err(dev->net, "Cannot change a running device\n");
-               ret = -EBUSY;
-               goto err;
-       }
-
        del_dev = qmimux_find_dev(dev, mux_id);
        if (!del_dev) {
                netdev_err(dev->net, "mux_id not present\n");
index b246817..90f1c02 100644 (file)
@@ -3021,29 +3021,6 @@ static void __rtl_set_wol(struct r8152 *tp, u32 wolopts)
                device_set_wakeup_enable(&tp->udev->dev, false);
 }
 
-static void r8153_mac_clk_spd(struct r8152 *tp, bool enable)
-{
-       /* MAC clock speed down */
-       if (enable) {
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL,
-                              ALDPS_SPDWN_RATIO);
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2,
-                              EEE_SPDWN_RATIO);
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,
-                              PKT_AVAIL_SPDWN_EN | SUSPEND_SPDWN_EN |
-                              U1U2_SPDWN_EN | L1_SPDWN_EN);
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
-                              PWRSAVE_SPDWN_EN | RXDV_SPDWN_EN | TX10MIDLE_EN |
-                              TP100_SPDWN_EN | TP500_SPDWN_EN | EEE_SPDWN_EN |
-                              TP1000_SPDWN_EN);
-       } else {
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0);
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0);
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0);
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0);
-       }
-}
-
 static void r8153_u1u2en(struct r8152 *tp, bool enable)
 {
        u8 u1u2[8];
@@ -3338,11 +3315,9 @@ static void rtl8153_runtime_enable(struct r8152 *tp, bool enable)
        if (enable) {
                r8153_u1u2en(tp, false);
                r8153_u2p3en(tp, false);
-               r8153_mac_clk_spd(tp, true);
                rtl_runtime_suspend_enable(tp, true);
        } else {
                rtl_runtime_suspend_enable(tp, false);
-               r8153_mac_clk_spd(tp, false);
 
                switch (tp->version) {
                case RTL_VER_03:
@@ -4718,7 +4693,6 @@ static void r8153_first_init(struct r8152 *tp)
 {
        u32 ocp_data;
 
-       r8153_mac_clk_spd(tp, false);
        rxdy_gated_en(tp, true);
        r8153_teredo_off(tp);
 
@@ -4769,8 +4743,6 @@ static void r8153_enter_oob(struct r8152 *tp)
 {
        u32 ocp_data;
 
-       r8153_mac_clk_spd(tp, true);
-
        ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
        ocp_data &= ~NOW_IS_OOB;
        ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
@@ -5496,10 +5468,15 @@ static void r8153_init(struct r8152 *tp)
 
        ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001);
 
+       /* MAC clock speed down */
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0);
+
        r8153_power_cut_en(tp, false);
        rtl_runtime_suspend_enable(tp, false);
        r8153_u1u2en(tp, true);
-       r8153_mac_clk_spd(tp, false);
        usb_enable_lpm(tp->udev);
 
        ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6);
index b4c8080..f4f37ec 100644 (file)
@@ -887,7 +887,7 @@ int usbnet_open (struct net_device *net)
 
        // insist peer be connected
        if (info->check_connect && (retval = info->check_connect (dev)) < 0) {
-               netif_dbg(dev, ifup, dev->net, "can't open; %d\n", retval);
+               netif_err(dev, ifup, dev->net, "can't open; %d\n", retval);
                goto done;
        }
 
index dca97cd..7eac6a3 100644 (file)
@@ -204,14 +204,18 @@ static int uhdlc_init(struct ucc_hdlc_private *priv)
        priv->rx_skbuff = kcalloc(priv->rx_ring_size,
                                  sizeof(*priv->rx_skbuff),
                                  GFP_KERNEL);
-       if (!priv->rx_skbuff)
+       if (!priv->rx_skbuff) {
+               ret = -ENOMEM;
                goto free_ucc_pram;
+       }
 
        priv->tx_skbuff = kcalloc(priv->tx_ring_size,
                                  sizeof(*priv->tx_skbuff),
                                  GFP_KERNEL);
-       if (!priv->tx_skbuff)
+       if (!priv->tx_skbuff) {
+               ret = -ENOMEM;
                goto free_rx_skbuff;
+       }
 
        priv->skb_curtx = 0;
        priv->skb_dirtytx = 0;
index 605fe55..c337249 100644 (file)
@@ -292,7 +292,6 @@ static int lapbeth_open(struct net_device *dev)
                return -ENODEV;
        }
 
-       netif_start_queue(dev);
        return 0;
 }
 
@@ -300,8 +299,6 @@ static int lapbeth_close(struct net_device *dev)
 {
        int err;
 
-       netif_stop_queue(dev);
-
        if ((err = lapb_unregister(dev)) != LAPB_OK)
                pr_err("lapb_unregister error: %d\n", err);
 
index b391169..faa2e67 100644 (file)
@@ -5450,8 +5450,8 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
        }
 
        if (ab->hw_params.vdev_start_delay &&
-           (arvif->vdev_type == WMI_VDEV_TYPE_AP ||
-           arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) {
+           arvif->vdev_type != WMI_VDEV_TYPE_AP &&
+           arvif->vdev_type != WMI_VDEV_TYPE_MONITOR) {
                param.vdev_id = arvif->vdev_id;
                param.peer_type = WMI_PEER_TYPE_DEFAULT;
                param.peer_addr = ar->mac_addr;
index 1aca841..7968fe4 100644 (file)
@@ -1687,8 +1687,8 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
                        req->mem_seg[i].size = ab->qmi.target_mem[i].size;
                        req->mem_seg[i].type = ab->qmi.target_mem[i].type;
                        ath11k_dbg(ab, ATH11K_DBG_QMI,
-                                  "qmi req mem_seg[%d] 0x%llx %u %u\n", i,
-                                   ab->qmi.target_mem[i].paddr,
+                                  "qmi req mem_seg[%d] %pad %u %u\n", i,
+                                   &ab->qmi.target_mem[i].paddr,
                                    ab->qmi.target_mem[i].size,
                                    ab->qmi.target_mem[i].type);
                }
index 13b4f5f..ef6f5ea 100644 (file)
@@ -177,7 +177,8 @@ struct ath_frame_info {
        s8 txq;
        u8 keyix;
        u8 rtscts_rate;
-       u8 retries : 7;
+       u8 retries : 6;
+       u8 dyn_smps : 1;
        u8 baw_tracked : 1;
        u8 tx_power;
        enum ath9k_key_type keytype:2;
index e60d473..5691bd6 100644 (file)
@@ -1271,6 +1271,11 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
                                 is_40, is_sgi, is_sp);
                        if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
                                info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
+                       if (rix >= 8 && fi->dyn_smps) {
+                               info->rates[i].RateFlags |=
+                                       ATH9K_RATESERIES_RTS_CTS;
+                               info->flags |= ATH9K_TXDESC_CTSENA;
+                       }
 
                        info->txpower[i] = ath_get_rate_txpower(sc, bf, rix,
                                                                is_40, false);
@@ -2114,6 +2119,7 @@ static void setup_frame_info(struct ieee80211_hw *hw,
                fi->keyix = an->ps_key;
        else
                fi->keyix = ATH9K_TXKEYIX_INVALID;
+       fi->dyn_smps = sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC;
        fi->keytype = keytype;
        fi->framelen = framelen;
        fi->tx_power = txpower;
index fd070ca..40f2109 100644 (file)
@@ -271,12 +271,12 @@ static int iwl_pnvm_get_from_efi(struct iwl_trans *trans,
        err = efivar_entry_get(pnvm_efivar, NULL, &package_size, package);
        if (err) {
                IWL_DEBUG_FW(trans,
-                            "PNVM UEFI variable not found %d (len %zd)\n",
+                            "PNVM UEFI variable not found %d (len %lu)\n",
                             err, package_size);
                goto out;
        }
 
-       IWL_DEBUG_FW(trans, "Read PNVM fro UEFI with size %zd\n", package_size);
+       IWL_DEBUG_FW(trans, "Read PNVM fro UEFI with size %lu\n", package_size);
 
        *data = kmemdup(package->data, *len, GFP_KERNEL);
        if (!*data)
index 868da7e..e6d2e09 100644 (file)
@@ -205,6 +205,8 @@ static inline void iwl_op_mode_time_point(struct iwl_op_mode *op_mode,
                                          enum iwl_fw_ini_time_point tp_id,
                                          union iwl_dbg_tlv_tp_data *tp_data)
 {
+       if (!op_mode || !op_mode->ops || !op_mode->ops->time_point)
+               return;
        op_mode->ops->time_point(op_mode, tp_id, tp_data);
 }
 
index 15e2773..5ee64f7 100644 (file)
@@ -1083,6 +1083,7 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = {
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek COMPUTER INC."),
                },
        },
+       {}
 };
 
 static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
index 314fec4..ffaf973 100644 (file)
@@ -1106,6 +1106,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                }
        }
 
+#if IS_ENABLED(CONFIG_IWLMVM)
+
        /*
         * Workaround for problematic SnJ device: sometimes when
         * certain RF modules are connected to SnJ, the device ID
@@ -1116,7 +1118,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_SNJ)
                iwl_trans->trans_cfg = &iwl_so_trans_cfg;
 
-#if IS_ENABLED(CONFIG_IWLMVM)
        /*
         * special-case 7265D, it has the same PCI IDs.
         *
index 42426e2..2bec971 100644 (file)
@@ -1129,6 +1129,8 @@ static int _iwl_pcie_rx_init(struct iwl_trans *trans)
 
                iwl_pcie_rx_init_rxb_lists(rxq);
 
+               spin_unlock_bh(&rxq->lock);
+
                if (!rxq->napi.poll) {
                        int (*poll)(struct napi_struct *, int) = iwl_pcie_napi_poll;
 
@@ -1149,7 +1151,6 @@ static int _iwl_pcie_rx_init(struct iwl_trans *trans)
                        napi_enable(&rxq->napi);
                }
 
-               spin_unlock_bh(&rxq->lock);
        }
 
        /* move the pool to the default queue and allocator ownerships */
index 19098b8..2f27c43 100644 (file)
@@ -345,7 +345,6 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
        };
        struct ieee80211_hw *hw;
        int len, n = 0, ret = -ENOMEM;
-       struct mt76_queue_entry e;
        struct mt76_txwi_cache *t;
        struct sk_buff *iter;
        dma_addr_t addr;
@@ -387,6 +386,11 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
        }
        tx_info.nbuf = n;
 
+       if (q->queued + (tx_info.nbuf + 1) / 2 >= q->ndesc - 1) {
+               ret = -ENOMEM;
+               goto unmap;
+       }
+
        dma_sync_single_for_cpu(dev->dev, t->dma_addr, dev->drv->txwi_size,
                                DMA_TO_DEVICE);
        ret = dev->drv->tx_prepare_skb(dev, txwi, q->qid, wcid, sta, &tx_info);
@@ -395,11 +399,6 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
        if (ret < 0)
                goto unmap;
 
-       if (q->queued + (tx_info.nbuf + 1) / 2 >= q->ndesc - 1) {
-               ret = -ENOMEM;
-               goto unmap;
-       }
-
        return mt76_dma_add_buf(dev, q, tx_info.buf, tx_info.nbuf,
                                tx_info.info, tx_info.skb, t);
 
@@ -419,9 +418,7 @@ free:
        }
 #endif
 
-       e.skb = tx_info.skb;
-       e.txwi = t;
-       dev->drv->tx_complete_skb(dev, &e);
+       dev_kfree_skb(tx_info.skb);
        mt76_put_txwi(dev, t);
        return ret;
 }
@@ -515,13 +512,13 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
 {
        struct sk_buff *skb = q->rx_head;
        struct skb_shared_info *shinfo = skb_shinfo(skb);
+       int nr_frags = shinfo->nr_frags;
 
-       if (shinfo->nr_frags < ARRAY_SIZE(shinfo->frags)) {
+       if (nr_frags < ARRAY_SIZE(shinfo->frags)) {
                struct page *page = virt_to_head_page(data);
                int offset = data - page_address(page) + q->buf_offset;
 
-               skb_add_rx_frag(skb, shinfo->nr_frags, page, offset, len,
-                               q->buf_size);
+               skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size);
        } else {
                skb_free_frag(data);
        }
@@ -530,7 +527,10 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
                return;
 
        q->rx_head = NULL;
-       dev->drv->rx_skb(dev, q - dev->q_rx, skb);
+       if (nr_frags < ARRAY_SIZE(shinfo->frags))
+               dev->drv->rx_skb(dev, q - dev->q_rx, skb);
+       else
+               dev_kfree_skb(skb);
 }
 
 static int
index eb889f8..e5a2589 100644 (file)
@@ -967,11 +967,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
        }
        txp->nbuf = nbuf;
 
-       /* pass partial skb header to fw */
-       tx_info->buf[1].len = MT_CT_PARSE_LEN;
-       tx_info->buf[1].skip_unmap = true;
-       tx_info->nbuf = MT_CT_DMA_BUF_NUM;
-
        txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD | MT_CT_INFO_FROM_HOST);
 
        if (!key)
@@ -1009,6 +1004,11 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
                txp->rept_wds_wcid = cpu_to_le16(0x3ff);
        tx_info->skb = DMA_DUMMY_DATA;
 
+       /* pass partial skb header to fw */
+       tx_info->buf[1].len = MT_CT_PARSE_LEN;
+       tx_info->buf[1].skip_unmap = true;
+       tx_info->nbuf = MT_CT_DMA_BUF_NUM;
+
        return 0;
 }
 
index 7fb2170..bd798df 100644 (file)
@@ -543,7 +543,7 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
                tx_cont->bw = CMD_CBW_20MHZ;
                break;
        default:
-               break;
+               return -EINVAL;
        }
 
        if (!en) {
@@ -591,7 +591,7 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
                mode = MT_PHY_TYPE_HE_MU;
                break;
        default:
-               break;
+               return -EINVAL;
        }
 
        rateval =  mode << 6 | rate_idx;
index db125cd..b5cc72e 100644 (file)
@@ -405,10 +405,8 @@ mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb,
        if (wlan_idx >= MT76_N_WCIDS)
                return;
        wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
-       if (!wcid) {
-               stats->tx_rate = rate;
+       if (!wcid)
                return;
-       }
 
        msta = container_of(wcid, struct mt7921_sta, wcid);
        stats = &msta->stats;
index 6afb5ca..39a01c2 100644 (file)
@@ -557,8 +557,8 @@ check_frags:
        }
 
        if (skb_has_frag_list(skb) && !first_shinfo) {
-               first_shinfo = skb_shinfo(skb);
-               shinfo = skb_shinfo(skb_shinfo(skb)->frag_list);
+               first_shinfo = shinfo;
+               shinfo = skb_shinfo(shinfo->frag_list);
                nr_frags = shinfo->nr_frags;
 
                goto check_frags;
index a1da83b..91acff4 100644 (file)
@@ -436,7 +436,7 @@ struct qeth_qdio_out_buffer {
        int is_header[QDIO_MAX_ELEMENTS_PER_BUFFER];
 
        struct qeth_qdio_out_q *q;
-       struct qeth_qdio_out_buffer *next_pending;
+       struct list_head list_entry;
 };
 
 struct qeth_card;
@@ -500,6 +500,7 @@ struct qeth_qdio_out_q {
        struct qdio_buffer *qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
        struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q];
        struct qdio_outbuf_state *bufstates; /* convenience pointer */
+       struct list_head pending_bufs;
        struct qeth_out_q_stats stats;
        spinlock_t lock;
        unsigned int priority;
index b71b890..a814698 100644 (file)
@@ -73,8 +73,6 @@ static void qeth_free_qdio_queues(struct qeth_card *card);
 static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
                struct qeth_qdio_out_buffer *buf,
                enum iucv_tx_notify notification);
-static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error,
-                                int budget);
 
 static void qeth_close_dev_handler(struct work_struct *work)
 {
@@ -465,41 +463,6 @@ static enum iucv_tx_notify qeth_compute_cq_notification(int sbalf15,
        return n;
 }
 
-static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx,
-                                        int forced_cleanup)
-{
-       if (q->card->options.cq != QETH_CQ_ENABLED)
-               return;
-
-       if (q->bufs[bidx]->next_pending != NULL) {
-               struct qeth_qdio_out_buffer *head = q->bufs[bidx];
-               struct qeth_qdio_out_buffer *c = q->bufs[bidx]->next_pending;
-
-               while (c) {
-                       if (forced_cleanup ||
-                           atomic_read(&c->state) == QETH_QDIO_BUF_EMPTY) {
-                               struct qeth_qdio_out_buffer *f = c;
-
-                               QETH_CARD_TEXT(f->q->card, 5, "fp");
-                               QETH_CARD_TEXT_(f->q->card, 5, "%lx", (long) f);
-                               /* release here to avoid interleaving between
-                                  outbound tasklet and inbound tasklet
-                                  regarding notifications and lifecycle */
-                               qeth_tx_complete_buf(c, forced_cleanup, 0);
-
-                               c = f->next_pending;
-                               WARN_ON_ONCE(head->next_pending != f);
-                               head->next_pending = c;
-                               kmem_cache_free(qeth_qdio_outbuf_cache, f);
-                       } else {
-                               head = c;
-                               c = c->next_pending;
-                       }
-
-               }
-       }
-}
-
 static void qeth_qdio_handle_aob(struct qeth_card *card,
                                 unsigned long phys_aob_addr)
 {
@@ -507,6 +470,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
        struct qaob *aob;
        struct qeth_qdio_out_buffer *buffer;
        enum iucv_tx_notify notification;
+       struct qeth_qdio_out_q *queue;
        unsigned int i;
 
        aob = (struct qaob *) phys_to_virt(phys_aob_addr);
@@ -537,7 +501,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
                qeth_notify_skbs(buffer->q, buffer, notification);
 
                /* Free dangling allocations. The attached skbs are handled by
-                * qeth_cleanup_handled_pending().
+                * qeth_tx_complete_pending_bufs().
                 */
                for (i = 0;
                     i < aob->sb_count && i < QETH_MAX_BUFFER_ELEMENTS(card);
@@ -549,7 +513,9 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
                        buffer->is_header[i] = 0;
                }
 
+               queue = buffer->q;
                atomic_set(&buffer->state, QETH_QDIO_BUF_EMPTY);
+               napi_schedule(&queue->napi);
                break;
        default:
                WARN_ON_ONCE(1);
@@ -1424,9 +1390,6 @@ static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error,
        struct qeth_qdio_out_q *queue = buf->q;
        struct sk_buff *skb;
 
-       if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING)
-               qeth_notify_skbs(queue, buf, TX_NOTIFY_GENERALERROR);
-
        /* Empty buffer? */
        if (buf->next_element_to_fill == 0)
                return;
@@ -1488,14 +1451,38 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
        atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
 }
 
+static void qeth_tx_complete_pending_bufs(struct qeth_card *card,
+                                         struct qeth_qdio_out_q *queue,
+                                         bool drain)
+{
+       struct qeth_qdio_out_buffer *buf, *tmp;
+
+       list_for_each_entry_safe(buf, tmp, &queue->pending_bufs, list_entry) {
+               if (drain || atomic_read(&buf->state) == QETH_QDIO_BUF_EMPTY) {
+                       QETH_CARD_TEXT(card, 5, "fp");
+                       QETH_CARD_TEXT_(card, 5, "%lx", (long) buf);
+
+                       if (drain)
+                               qeth_notify_skbs(queue, buf,
+                                                TX_NOTIFY_GENERALERROR);
+                       qeth_tx_complete_buf(buf, drain, 0);
+
+                       list_del(&buf->list_entry);
+                       kmem_cache_free(qeth_qdio_outbuf_cache, buf);
+               }
+       }
+}
+
 static void qeth_drain_output_queue(struct qeth_qdio_out_q *q, bool free)
 {
        int j;
 
+       qeth_tx_complete_pending_bufs(q->card, q, true);
+
        for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
                if (!q->bufs[j])
                        continue;
-               qeth_cleanup_handled_pending(q, j, 1);
+
                qeth_clear_output_buffer(q, q->bufs[j], true, 0);
                if (free) {
                        kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[j]);
@@ -2615,7 +2602,6 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
        skb_queue_head_init(&newbuf->skb_list);
        lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key);
        newbuf->q = q;
-       newbuf->next_pending = q->bufs[bidx];
        atomic_set(&newbuf->state, QETH_QDIO_BUF_EMPTY);
        q->bufs[bidx] = newbuf;
        return 0;
@@ -2634,15 +2620,28 @@ static void qeth_free_output_queue(struct qeth_qdio_out_q *q)
 static struct qeth_qdio_out_q *qeth_alloc_output_queue(void)
 {
        struct qeth_qdio_out_q *q = kzalloc(sizeof(*q), GFP_KERNEL);
+       unsigned int i;
 
        if (!q)
                return NULL;
 
-       if (qdio_alloc_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q)) {
-               kfree(q);
-               return NULL;
+       if (qdio_alloc_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q))
+               goto err_qdio_bufs;
+
+       for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
+               if (qeth_init_qdio_out_buf(q, i))
+                       goto err_out_bufs;
        }
+
        return q;
+
+err_out_bufs:
+       while (i > 0)
+               kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[--i]);
+       qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
+err_qdio_bufs:
+       kfree(q);
+       return NULL;
 }
 
 static void qeth_tx_completion_timer(struct timer_list *timer)
@@ -2655,7 +2654,7 @@ static void qeth_tx_completion_timer(struct timer_list *timer)
 
 static int qeth_alloc_qdio_queues(struct qeth_card *card)
 {
-       int i, j;
+       unsigned int i;
 
        QETH_CARD_TEXT(card, 2, "allcqdbf");
 
@@ -2684,18 +2683,12 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card)
                card->qdio.out_qs[i] = queue;
                queue->card = card;
                queue->queue_no = i;
+               INIT_LIST_HEAD(&queue->pending_bufs);
                spin_lock_init(&queue->lock);
                timer_setup(&queue->timer, qeth_tx_completion_timer, 0);
                queue->coalesce_usecs = QETH_TX_COALESCE_USECS;
                queue->max_coalesced_frames = QETH_TX_MAX_COALESCED_FRAMES;
                queue->priority = QETH_QIB_PQUE_PRIO_DEFAULT;
-
-               /* give outbound qeth_qdio_buffers their qdio_buffers */
-               for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
-                       WARN_ON(queue->bufs[j]);
-                       if (qeth_init_qdio_out_buf(queue, j))
-                               goto out_freeoutqbufs;
-               }
        }
 
        /* completion */
@@ -2704,13 +2697,6 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card)
 
        return 0;
 
-out_freeoutqbufs:
-       while (j > 0) {
-               --j;
-               kmem_cache_free(qeth_qdio_outbuf_cache,
-                               card->qdio.out_qs[i]->bufs[j]);
-               card->qdio.out_qs[i]->bufs[j] = NULL;
-       }
 out_freeoutq:
        while (i > 0) {
                qeth_free_output_queue(card->qdio.out_qs[--i]);
@@ -6107,6 +6093,8 @@ static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue,
                                        qeth_schedule_recovery(card);
                                }
 
+                               list_add(&buffer->list_entry,
+                                        &queue->pending_bufs);
                                /* Skip clearing the buffer: */
                                return;
                        case QETH_QDIO_BUF_QAOB_OK:
@@ -6162,6 +6150,8 @@ static int qeth_tx_poll(struct napi_struct *napi, int budget)
                unsigned int bytes = 0;
                int completed;
 
+               qeth_tx_complete_pending_bufs(card, queue, false);
+
                if (qeth_out_queue_is_empty(queue)) {
                        napi_complete(napi);
                        return 0;
@@ -6194,7 +6184,6 @@ static int qeth_tx_poll(struct napi_struct *napi, int budget)
 
                        qeth_handle_send_error(card, buffer, error);
                        qeth_iqd_tx_complete(queue, bidx, error, budget);
-                       qeth_cleanup_handled_pending(queue, bidx, false);
                }
 
                netdev_tx_completed_queue(txq, packets, bytes);
@@ -7249,9 +7238,7 @@ int qeth_open(struct net_device *dev)
        card->data.state = CH_STATE_UP;
        netif_tx_start_all_queues(dev);
 
-       napi_enable(&card->napi);
        local_bh_disable();
-       napi_schedule(&card->napi);
        if (IS_IQD(card)) {
                struct qeth_qdio_out_q *queue;
                unsigned int i;
@@ -7263,8 +7250,12 @@ int qeth_open(struct net_device *dev)
                        napi_schedule(&queue->napi);
                }
        }
+
+       napi_enable(&card->napi);
+       napi_schedule(&card->napi);
        /* kick-start the NAPI softirq: */
        local_bh_enable();
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(qeth_open);
@@ -7274,6 +7265,11 @@ int qeth_stop(struct net_device *dev)
        struct qeth_card *card = dev->ml_priv;
 
        QETH_CARD_TEXT(card, 4, "qethstop");
+
+       napi_disable(&card->napi);
+       cancel_delayed_work_sync(&card->buffer_reclaim_work);
+       qdio_stop_irq(CARD_DDEV(card));
+
        if (IS_IQD(card)) {
                struct qeth_qdio_out_q *queue;
                unsigned int i;
@@ -7294,10 +7290,6 @@ int qeth_stop(struct net_device *dev)
                netif_tx_disable(dev);
        }
 
-       napi_disable(&card->napi);
-       cancel_delayed_work_sync(&card->buffer_reclaim_work);
-       qdio_stop_irq(CARD_DDEV(card));
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(qeth_stop);
index 60cd25c..9b02961 100644 (file)
@@ -151,7 +151,7 @@ struct atm_dev {
        const char      *type;          /* device type name */
        int             number;         /* device index */
        void            *dev_data;      /* per-device data */
-       void            *phy_data;      /* private PHY date */
+       void            *phy_data;      /* private PHY data */
        unsigned long   flags;          /* device flags (ATM_DF_*) */
        struct list_head local;         /* local ATM addresses */
        struct list_head lecs;          /* LECS ATM addresses learned via ILMI */
index 685f34c..d438eb0 100644 (file)
@@ -65,8 +65,12 @@ static inline void can_skb_reserve(struct sk_buff *skb)
 
 static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk)
 {
-       if (sk) {
-               sock_hold(sk);
+       /* If the socket has already been closed by user space, the
+        * refcount may already be 0 (and the socket will be freed
+        * after the last TX skb has been freed). So only increase
+        * socket refcount if the refcount is > 0.
+        */
+       if (sk && refcount_inc_not_zero(&sk->sk_refcnt)) {
                skb->destructor = sock_efree;
                skb->sk = sk;
        }
index f06fbee..5b67ea8 100644 (file)
@@ -3959,8 +3959,6 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
 int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
 u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode);
 
-int xdp_umem_query(struct net_device *dev, u16 queue_id);
-
 int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 int dev_forward_skb_nomtu(struct net_device *dev, struct sk_buff *skb);
index 13770cf..6673e4d 100644 (file)
@@ -23,7 +23,7 @@ struct ts_config;
 struct ts_state
 {
        unsigned int            offset;
-       char                    cb[40];
+       char                    cb[48];
 };
 
 /**
index e8a924e..6b5fcfa 100644 (file)
@@ -79,8 +79,13 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
                if (gso_type && skb->network_header) {
                        struct flow_keys_basic keys;
 
-                       if (!skb->protocol)
+                       if (!skb->protocol) {
+                               __be16 protocol = dev_parse_header_protocol(skb);
+
                                virtio_net_hdr_set_proto(skb, hdr);
+                               if (protocol && protocol != skb->protocol)
+                                       return -EINVAL;
+                       }
 retry:
                        if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys,
                                                              NULL, 0, 0, 0,
index 4c24daa..79c8933 100644 (file)
@@ -3850,7 +3850,6 @@ union bpf_attr {
  *
  * long bpf_check_mtu(void *ctx, u32 ifindex, u32 *mtu_len, s32 len_diff, u64 flags)
  *     Description
-
  *             Check ctx packet size against exceeding MTU of net device (based
  *             on *ifindex*).  This helper will likely be used in combination
  *             with helpers that adjust/change the packet size.
index 30c80d5..bab8c97 100644 (file)
@@ -145,6 +145,7 @@ enum {
        L2TP_ATTR_RX_ERRORS,            /* u64 */
        L2TP_ATTR_STATS_PAD,
        L2TP_ATTR_RX_COOKIE_DISCARDS,   /* u64 */
+       L2TP_ATTR_RX_INVALID,           /* u64 */
        __L2TP_ATTR_STATS_MAX,
 };
 
index a13137a..70af020 100644 (file)
@@ -5,7 +5,7 @@
 #define NFCT_HELPER_STATUS_DISABLED    0
 #define NFCT_HELPER_STATUS_ENABLED     1
 
-enum nfnl_acct_msg_types {
+enum nfnl_cthelper_msg_types {
        NFNL_MSG_CTHELPER_NEW,
        NFNL_MSG_CTHELPER_GET,
        NFNL_MSG_CTHELPER_DEL,
index 2efeb5f..b1a76fe 100644 (file)
@@ -4321,8 +4321,6 @@ btf_get_prog_ctx_type(struct bpf_verifier_log *log, struct btf *btf,
                 * is not supported yet.
                 * BPF_PROG_TYPE_RAW_TRACEPOINT is fine.
                 */
-               if (log->level & BPF_LOG_LEVEL)
-                       bpf_log(log, "arg#%d type is not a struct\n", arg);
                return NULL;
        }
        tname = btf_name_by_offset(btf, t->name_off);
index 0ae015a..3a283bf 100644 (file)
@@ -1118,6 +1118,8 @@ static void bpf_prog_clone_free(struct bpf_prog *fp)
         * clone is guaranteed to not be locked.
         */
        fp->aux = NULL;
+       fp->stats = NULL;
+       fp->active = NULL;
        __bpf_prog_free(fp);
 }
 
@@ -2342,6 +2344,10 @@ bool __weak bpf_helper_changes_pkt_data(void *func)
 /* Return TRUE if the JIT backend wants verifier to enable sub-register usage
  * analysis code and wants explicit zero extension inserted by verifier.
  * Otherwise, return FALSE.
+ *
+ * The verifier inserts an explicit zero extension after BPF_CMPXCHGs even if
+ * you don't override this. JITs that don't want these extra insns can detect
+ * them using insn_is_zext.
  */
 bool __weak bpf_jit_needs_zext(void)
 {
index 1dda9d8..c56e3fc 100644 (file)
@@ -504,6 +504,13 @@ static bool is_ptr_cast_function(enum bpf_func_id func_id)
                func_id == BPF_FUNC_skc_to_tcp_request_sock;
 }
 
+static bool is_cmpxchg_insn(const struct bpf_insn *insn)
+{
+       return BPF_CLASS(insn->code) == BPF_STX &&
+              BPF_MODE(insn->code) == BPF_ATOMIC &&
+              insn->imm == BPF_CMPXCHG;
+}
+
 /* string representation of 'enum bpf_reg_type' */
 static const char * const reg_type_str[] = {
        [NOT_INIT]              = "?",
@@ -1120,7 +1127,7 @@ static void mark_ptr_not_null_reg(struct bpf_reg_state *reg)
                reg->type = PTR_TO_RDWR_BUF;
                break;
        default:
-               WARN_ON("unknown nullable register type");
+               WARN_ONCE(1, "unknown nullable register type");
        }
 }
 
@@ -1703,7 +1710,11 @@ static bool is_reg64(struct bpf_verifier_env *env, struct bpf_insn *insn,
        }
 
        if (class == BPF_STX) {
-               if (reg->type != SCALAR_VALUE)
+               /* BPF_STX (including atomic variants) has multiple source
+                * operands, one of which is a ptr. Check whether the caller is
+                * asking about it.
+                */
+               if (t == SRC_OP && reg->type != SCALAR_VALUE)
                        return true;
                return BPF_SIZE(code) == BPF_DW;
        }
@@ -1735,22 +1746,38 @@ static bool is_reg64(struct bpf_verifier_env *env, struct bpf_insn *insn,
        return true;
 }
 
-/* Return TRUE if INSN doesn't have explicit value define. */
-static bool insn_no_def(struct bpf_insn *insn)
+/* Return the regno defined by the insn, or -1. */
+static int insn_def_regno(const struct bpf_insn *insn)
 {
-       u8 class = BPF_CLASS(insn->code);
-
-       return (class == BPF_JMP || class == BPF_JMP32 ||
-               class == BPF_STX || class == BPF_ST);
+       switch (BPF_CLASS(insn->code)) {
+       case BPF_JMP:
+       case BPF_JMP32:
+       case BPF_ST:
+               return -1;
+       case BPF_STX:
+               if (BPF_MODE(insn->code) == BPF_ATOMIC &&
+                   (insn->imm & BPF_FETCH)) {
+                       if (insn->imm == BPF_CMPXCHG)
+                               return BPF_REG_0;
+                       else
+                               return insn->src_reg;
+               } else {
+                       return -1;
+               }
+       default:
+               return insn->dst_reg;
+       }
 }
 
 /* Return TRUE if INSN has defined any 32-bit value explicitly. */
 static bool insn_has_def32(struct bpf_verifier_env *env, struct bpf_insn *insn)
 {
-       if (insn_no_def(insn))
+       int dst_reg = insn_def_regno(insn);
+
+       if (dst_reg == -1)
                return false;
 
-       return !is_reg64(env, insn, insn->dst_reg, NULL, DST_OP);
+       return !is_reg64(env, insn, dst_reg, NULL, DST_OP);
 }
 
 static void mark_insn_zext(struct bpf_verifier_env *env,
@@ -11006,9 +11033,10 @@ static int opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env,
        for (i = 0; i < len; i++) {
                int adj_idx = i + delta;
                struct bpf_insn insn;
-               u8 load_reg;
+               int load_reg;
 
                insn = insns[adj_idx];
+               load_reg = insn_def_regno(&insn);
                if (!aux[adj_idx].zext_dst) {
                        u8 code, class;
                        u32 imm_rnd;
@@ -11018,14 +11046,14 @@ static int opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env,
 
                        code = insn.code;
                        class = BPF_CLASS(code);
-                       if (insn_no_def(&insn))
+                       if (load_reg == -1)
                                continue;
 
                        /* NOTE: arg "reg" (the fourth one) is only used for
-                        *       BPF_STX which has been ruled out in above
-                        *       check, it is safe to pass NULL here.
+                        *       BPF_STX + SRC_OP, so it is safe to pass NULL
+                        *       here.
                         */
-                       if (is_reg64(env, &insn, insn.dst_reg, NULL, DST_OP)) {
+                       if (is_reg64(env, &insn, load_reg, NULL, DST_OP)) {
                                if (class == BPF_LD &&
                                    BPF_MODE(code) == BPF_IMM)
                                        i++;
@@ -11040,31 +11068,28 @@ static int opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env,
                        imm_rnd = get_random_int();
                        rnd_hi32_patch[0] = insn;
                        rnd_hi32_patch[1].imm = imm_rnd;
-                       rnd_hi32_patch[3].dst_reg = insn.dst_reg;
+                       rnd_hi32_patch[3].dst_reg = load_reg;
                        patch = rnd_hi32_patch;
                        patch_len = 4;
                        goto apply_patch_buffer;
                }
 
-               if (!bpf_jit_needs_zext())
+               /* Add in an zero-extend instruction if a) the JIT has requested
+                * it or b) it's a CMPXCHG.
+                *
+                * The latter is because: BPF_CMPXCHG always loads a value into
+                * R0, therefore always zero-extends. However some archs'
+                * equivalent instruction only does this load when the
+                * comparison is successful. This detail of CMPXCHG is
+                * orthogonal to the general zero-extension behaviour of the
+                * CPU, so it's treated independently of bpf_jit_needs_zext.
+                */
+               if (!bpf_jit_needs_zext() && !is_cmpxchg_insn(&insn))
                        continue;
 
-               /* zext_dst means that we want to zero-extend whatever register
-                * the insn defines, which is dst_reg most of the time, with
-                * the notable exception of BPF_STX + BPF_ATOMIC + BPF_FETCH.
-                */
-               if (BPF_CLASS(insn.code) == BPF_STX &&
-                   BPF_MODE(insn.code) == BPF_ATOMIC) {
-                       /* BPF_STX + BPF_ATOMIC insns without BPF_FETCH do not
-                        * define any registers, therefore zext_dst cannot be
-                        * set.
-                        */
-                       if (WARN_ON(!(insn.imm & BPF_FETCH)))
-                               return -EINVAL;
-                       load_reg = insn.imm == BPF_CMPXCHG ? BPF_REG_0
-                                                          : insn.src_reg;
-               } else {
-                       load_reg = insn.dst_reg;
+               if (WARN_ON(load_reg == -1)) {
+                       verbose(env, "verifier bug. zext_dst is set, but no reg is defined\n");
+                       return -EFAULT;
                }
 
                zext_patch[0] = insn;
index 4f62f29..0a9019d 100644 (file)
@@ -1623,10 +1623,6 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
        }
 
        p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
-       if (!count) {
-               p9_tag_remove(clnt, req);
-               return 0;
-       }
 
        if (non_zc) {
                int n = copy_to_iter(dataptr, count, to);
index 0edc0b2..1bdcb33 100644 (file)
@@ -2147,7 +2147,7 @@ out:
 out_err:
        cb->args[1] = idx;
        cb->args[0] = h;
-       cb->seq = net->dev_base_seq;
+       cb->seq = tgt_net->dev_base_seq;
        nl_dump_check_consistent(cb, nlmsg_hdr(skb));
        if (netnsid >= 0)
                put_net(tgt_net);
index 545a472..c421c8f 100644 (file)
@@ -3659,6 +3659,8 @@ unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,
        struct ts_state state;
        unsigned int ret;
 
+       BUILD_BUG_ON(sizeof(struct skb_seq_state) > sizeof(state.cb));
+
        config->get_next_block = skb_ts_get_next_block;
        config->finish = skb_ts_finish;
 
index 3589224..58b8fc8 100644 (file)
@@ -118,6 +118,8 @@ config NET_DSA_TAG_OCELOT
 
 config NET_DSA_TAG_OCELOT_8021Q
        tristate "Tag driver for Ocelot family of switches, using VLAN"
+       depends on MSCC_OCELOT_SWITCH_LIB || \
+                 (MSCC_OCELOT_SWITCH_LIB=n && COMPILE_TEST)
        select NET_DSA_TAG_8021Q
        help
          Say Y or M if you want to enable support for tagging frames with a
index 2eeaa42..9d4b0e9 100644 (file)
@@ -230,8 +230,8 @@ int dsa_port_hsr_join(struct dsa_port *dp, struct net_device *hsr);
 void dsa_port_hsr_leave(struct dsa_port *dp, struct net_device *hsr);
 extern const struct phylink_mac_ops dsa_port_phylink_mac_ops;
 
-static inline bool dsa_port_offloads_netdev(struct dsa_port *dp,
-                                           struct net_device *dev)
+static inline bool dsa_port_offloads_bridge_port(struct dsa_port *dp,
+                                                struct net_device *dev)
 {
        /* Switchdev offloading can be configured on: */
 
@@ -241,12 +241,6 @@ static inline bool dsa_port_offloads_netdev(struct dsa_port *dp,
                 */
                return true;
 
-       if (dp->bridge_dev == dev)
-               /* DSA ports connected to a bridge, and event was emitted
-                * for the bridge.
-                */
-               return true;
-
        if (dp->lag_dev == dev)
                /* DSA ports connected to a bridge via a LAG */
                return true;
@@ -254,14 +248,23 @@ static inline bool dsa_port_offloads_netdev(struct dsa_port *dp,
        return false;
 }
 
+static inline bool dsa_port_offloads_bridge(struct dsa_port *dp,
+                                           struct net_device *bridge_dev)
+{
+       /* DSA ports connected to a bridge, and event was emitted
+        * for the bridge.
+        */
+       return dp->bridge_dev == bridge_dev;
+}
+
 /* Returns true if any port of this tree offloads the given net_device */
-static inline bool dsa_tree_offloads_netdev(struct dsa_switch_tree *dst,
-                                           struct net_device *dev)
+static inline bool dsa_tree_offloads_bridge_port(struct dsa_switch_tree *dst,
+                                                struct net_device *dev)
 {
        struct dsa_port *dp;
 
        list_for_each_entry(dp, &dst->ports, list)
-               if (dsa_port_offloads_netdev(dp, dev))
+               if (dsa_port_offloads_bridge_port(dp, dev))
                        return true;
 
        return false;
index 491e376..992fcab 100644 (file)
@@ -278,28 +278,43 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
        struct dsa_port *dp = dsa_slave_to_port(dev);
        int ret;
 
-       if (!dsa_port_offloads_netdev(dp, attr->orig_dev))
-               return -EOPNOTSUPP;
-
        switch (attr->id) {
        case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
+               if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev))
+                       return -EOPNOTSUPP;
+
                ret = dsa_port_set_state(dp, attr->u.stp_state);
                break;
        case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
+               if (!dsa_port_offloads_bridge(dp, attr->orig_dev))
+                       return -EOPNOTSUPP;
+
                ret = dsa_port_vlan_filtering(dp, attr->u.vlan_filtering,
                                              extack);
                break;
        case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
+               if (!dsa_port_offloads_bridge(dp, attr->orig_dev))
+                       return -EOPNOTSUPP;
+
                ret = dsa_port_ageing_time(dp, attr->u.ageing_time);
                break;
        case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
+               if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev))
+                       return -EOPNOTSUPP;
+
                ret = dsa_port_pre_bridge_flags(dp, attr->u.brport_flags,
                                                extack);
                break;
        case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
+               if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev))
+                       return -EOPNOTSUPP;
+
                ret = dsa_port_bridge_flags(dp, attr->u.brport_flags, extack);
                break;
        case SWITCHDEV_ATTR_ID_BRIDGE_MROUTER:
+               if (!dsa_port_offloads_bridge(dp, attr->orig_dev))
+                       return -EOPNOTSUPP;
+
                ret = dsa_port_mrouter(dp->cpu_dp, attr->u.mrouter, extack);
                break;
        default:
@@ -341,9 +356,6 @@ static int dsa_slave_vlan_add(struct net_device *dev,
        struct switchdev_obj_port_vlan vlan;
        int err;
 
-       if (!dsa_port_offloads_netdev(dp, obj->orig_dev))
-               return -EOPNOTSUPP;
-
        if (dsa_port_skip_vlan_configuration(dp)) {
                NL_SET_ERR_MSG_MOD(extack, "skipping configuration of VLAN");
                return 0;
@@ -391,27 +403,36 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
 
        switch (obj->id) {
        case SWITCHDEV_OBJ_ID_PORT_MDB:
-               if (!dsa_port_offloads_netdev(dp, obj->orig_dev))
+               if (!dsa_port_offloads_bridge_port(dp, obj->orig_dev))
                        return -EOPNOTSUPP;
+
                err = dsa_port_mdb_add(dp, SWITCHDEV_OBJ_PORT_MDB(obj));
                break;
        case SWITCHDEV_OBJ_ID_HOST_MDB:
+               if (!dsa_port_offloads_bridge(dp, obj->orig_dev))
+                       return -EOPNOTSUPP;
+
                /* DSA can directly translate this to a normal MDB add,
                 * but on the CPU port.
                 */
                err = dsa_port_mdb_add(dp->cpu_dp, SWITCHDEV_OBJ_PORT_MDB(obj));
                break;
        case SWITCHDEV_OBJ_ID_PORT_VLAN:
+               if (!dsa_port_offloads_bridge_port(dp, obj->orig_dev))
+                       return -EOPNOTSUPP;
+
                err = dsa_slave_vlan_add(dev, obj, extack);
                break;
        case SWITCHDEV_OBJ_ID_MRP:
-               if (!dsa_port_offloads_netdev(dp, obj->orig_dev))
+               if (!dsa_port_offloads_bridge(dp, obj->orig_dev))
                        return -EOPNOTSUPP;
+
                err = dsa_port_mrp_add(dp, SWITCHDEV_OBJ_MRP(obj));
                break;
        case SWITCHDEV_OBJ_ID_RING_ROLE_MRP:
-               if (!dsa_port_offloads_netdev(dp, obj->orig_dev))
+               if (!dsa_port_offloads_bridge(dp, obj->orig_dev))
                        return -EOPNOTSUPP;
+
                err = dsa_port_mrp_add_ring_role(dp,
                                                 SWITCHDEV_OBJ_RING_ROLE_MRP(obj));
                break;
@@ -431,9 +452,6 @@ static int dsa_slave_vlan_del(struct net_device *dev,
        struct switchdev_obj_port_vlan *vlan;
        int err;
 
-       if (!dsa_port_offloads_netdev(dp, obj->orig_dev))
-               return -EOPNOTSUPP;
-
        if (dsa_port_skip_vlan_configuration(dp))
                return 0;
 
@@ -459,27 +477,36 @@ static int dsa_slave_port_obj_del(struct net_device *dev,
 
        switch (obj->id) {
        case SWITCHDEV_OBJ_ID_PORT_MDB:
-               if (!dsa_port_offloads_netdev(dp, obj->orig_dev))
+               if (!dsa_port_offloads_bridge_port(dp, obj->orig_dev))
                        return -EOPNOTSUPP;
+
                err = dsa_port_mdb_del(dp, SWITCHDEV_OBJ_PORT_MDB(obj));
                break;
        case SWITCHDEV_OBJ_ID_HOST_MDB:
+               if (!dsa_port_offloads_bridge(dp, obj->orig_dev))
+                       return -EOPNOTSUPP;
+
                /* DSA can directly translate this to a normal MDB add,
                 * but on the CPU port.
                 */
                err = dsa_port_mdb_del(dp->cpu_dp, SWITCHDEV_OBJ_PORT_MDB(obj));
                break;
        case SWITCHDEV_OBJ_ID_PORT_VLAN:
+               if (!dsa_port_offloads_bridge_port(dp, obj->orig_dev))
+                       return -EOPNOTSUPP;
+
                err = dsa_slave_vlan_del(dev, obj);
                break;
        case SWITCHDEV_OBJ_ID_MRP:
-               if (!dsa_port_offloads_netdev(dp, obj->orig_dev))
+               if (!dsa_port_offloads_bridge(dp, obj->orig_dev))
                        return -EOPNOTSUPP;
+
                err = dsa_port_mrp_del(dp, SWITCHDEV_OBJ_MRP(obj));
                break;
        case SWITCHDEV_OBJ_ID_RING_ROLE_MRP:
-               if (!dsa_port_offloads_netdev(dp, obj->orig_dev))
+               if (!dsa_port_offloads_bridge(dp, obj->orig_dev))
                        return -EOPNOTSUPP;
+
                err = dsa_port_mrp_del_ring_role(dp,
                                                 SWITCHDEV_OBJ_RING_ROLE_MRP(obj));
                break;
@@ -2298,7 +2325,7 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
                         * other ports bridged with the LAG should be able to
                         * autonomously forward towards it.
                         */
-                       if (dsa_tree_offloads_netdev(dp->ds->dst, dev))
+                       if (dsa_tree_offloads_bridge_port(dp->ds->dst, dev))
                                return NOTIFY_DONE;
                }
 
index 38dcdde..5974848 100644 (file)
@@ -13,6 +13,7 @@
 #define MTK_HDR_LEN            4
 #define MTK_HDR_XMIT_UNTAGGED          0
 #define MTK_HDR_XMIT_TAGGED_TPID_8100  1
+#define MTK_HDR_XMIT_TAGGED_TPID_88A8  2
 #define MTK_HDR_RECV_SOURCE_PORT_MASK  GENMASK(2, 0)
 #define MTK_HDR_XMIT_DP_BIT_MASK       GENMASK(5, 0)
 #define MTK_HDR_XMIT_SA_DIS            BIT(6)
@@ -21,8 +22,8 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
                                    struct net_device *dev)
 {
        struct dsa_port *dp = dsa_slave_to_port(dev);
+       u8 xmit_tpid;
        u8 *mtk_tag;
-       bool is_vlan_skb = true;
        unsigned char *dest = eth_hdr(skb)->h_dest;
        bool is_multicast_skb = is_multicast_ether_addr(dest) &&
                                !is_broadcast_ether_addr(dest);
@@ -33,10 +34,17 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
         * the both special and VLAN tag at the same time and then look up VLAN
         * table with VID.
         */
-       if (!skb_vlan_tagged(skb)) {
+       switch (skb->protocol) {
+       case htons(ETH_P_8021Q):
+               xmit_tpid = MTK_HDR_XMIT_TAGGED_TPID_8100;
+               break;
+       case htons(ETH_P_8021AD):
+               xmit_tpid = MTK_HDR_XMIT_TAGGED_TPID_88A8;
+               break;
+       default:
+               xmit_tpid = MTK_HDR_XMIT_UNTAGGED;
                skb_push(skb, MTK_HDR_LEN);
                memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
-               is_vlan_skb = false;
        }
 
        mtk_tag = skb->data + 2 * ETH_ALEN;
@@ -44,8 +52,7 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
        /* Mark tag attribute on special tag insertion to notify hardware
         * whether that's a combined special tag with 802.1Q header.
         */
-       mtk_tag[0] = is_vlan_skb ? MTK_HDR_XMIT_TAGGED_TPID_8100 :
-                    MTK_HDR_XMIT_UNTAGGED;
+       mtk_tag[0] = xmit_tpid;
        mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
 
        /* Disable SA learning for multicast frames */
@@ -53,7 +60,7 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
                mtk_tag[1] |= MTK_HDR_XMIT_SA_DIS;
 
        /* Tag control information is kept for 802.1Q */
-       if (!is_vlan_skb) {
+       if (xmit_tpid == MTK_HDR_XMIT_UNTAGGED) {
                mtk_tag[2] = 0;
                mtk_tag[3] = 0;
        }
index c17d39b..e917647 100644 (file)
@@ -35,14 +35,12 @@ static struct sk_buff *rtl4a_tag_xmit(struct sk_buff *skb,
                                      struct net_device *dev)
 {
        struct dsa_port *dp = dsa_slave_to_port(dev);
+       __be16 *p;
        u8 *tag;
-       u16 *p;
        u16 out;
 
        /* Pad out to at least 60 bytes */
-       if (unlikely(eth_skb_pad(skb)))
-               return NULL;
-       if (skb_cow_head(skb, RTL4_A_HDR_LEN) < 0)
+       if (unlikely(__skb_put_padto(skb, ETH_ZLEN, false)))
                return NULL;
 
        netdev_dbg(dev, "add realtek tag to package to port %d\n",
@@ -53,13 +51,13 @@ static struct sk_buff *rtl4a_tag_xmit(struct sk_buff *skb,
        tag = skb->data + 2 * ETH_ALEN;
 
        /* Set Ethertype */
-       p = (u16 *)tag;
+       p = (__be16 *)tag;
        *p = htons(RTL4_A_ETHERTYPE);
 
        out = (RTL4_A_PROTOCOL_RTL8366RB << 12) | (2 << 8);
-       /* The lower bits is the port numer */
+       /* The lower bits is the port number */
        out |= (u8)dp->index;
-       p = (u16 *)(tag + 2);
+       p = (__be16 *)(tag + 2);
        *p = htons(out);
 
        return skb;
index 25a9e56..6a070dc 100644 (file)
@@ -116,10 +116,9 @@ int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info)
        struct ethtool_channels channels = {};
        struct ethnl_req_info req_info = {};
        struct nlattr **tb = info->attrs;
-       const struct nlattr *err_attr;
+       u32 err_attr, max_rx_in_use = 0;
        const struct ethtool_ops *ops;
        struct net_device *dev;
-       u32 max_rx_in_use = 0;
        int ret;
 
        ret = ethnl_parse_header_dev_get(&req_info,
@@ -157,34 +156,35 @@ int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info)
 
        /* ensure new channel counts are within limits */
        if (channels.rx_count > channels.max_rx)
-               err_attr = tb[ETHTOOL_A_CHANNELS_RX_COUNT];
+               err_attr = ETHTOOL_A_CHANNELS_RX_COUNT;
        else if (channels.tx_count > channels.max_tx)
-               err_attr = tb[ETHTOOL_A_CHANNELS_TX_COUNT];
+               err_attr = ETHTOOL_A_CHANNELS_TX_COUNT;
        else if (channels.other_count > channels.max_other)
-               err_attr = tb[ETHTOOL_A_CHANNELS_OTHER_COUNT];
+               err_attr = ETHTOOL_A_CHANNELS_OTHER_COUNT;
        else if (channels.combined_count > channels.max_combined)
-               err_attr = tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT];
+               err_attr = ETHTOOL_A_CHANNELS_COMBINED_COUNT;
        else
-               err_attr = NULL;
+               err_attr = 0;
        if (err_attr) {
                ret = -EINVAL;
-               NL_SET_ERR_MSG_ATTR(info->extack, err_attr,
+               NL_SET_ERR_MSG_ATTR(info->extack, tb[err_attr],
                                    "requested channel count exceeds maximum");
                goto out_ops;
        }
 
        /* ensure there is at least one RX and one TX channel */
        if (!channels.combined_count && !channels.rx_count)
-               err_attr = tb[ETHTOOL_A_CHANNELS_RX_COUNT];
+               err_attr = ETHTOOL_A_CHANNELS_RX_COUNT;
        else if (!channels.combined_count && !channels.tx_count)
-               err_attr = tb[ETHTOOL_A_CHANNELS_TX_COUNT];
+               err_attr = ETHTOOL_A_CHANNELS_TX_COUNT;
        else
-               err_attr = NULL;
+               err_attr = 0;
        if (err_attr) {
                if (mod_combined)
-                       err_attr = tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT];
+                       err_attr = ETHTOOL_A_CHANNELS_COMBINED_COUNT;
                ret = -EINVAL;
-               NL_SET_ERR_MSG_ATTR(info->extack, err_attr, "requested channel counts would result in no RX or TX channel being configured");
+               NL_SET_ERR_MSG_ATTR(info->extack, tb[err_attr],
+                                   "requested channel counts would result in no RX or TX channel being configured");
                goto out_ops;
        }
 
index 471d33a..bfaf327 100644 (file)
@@ -519,16 +519,10 @@ int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info)
                ret_val = -ENOENT;
                goto doi_remove_return;
        }
-       if (!refcount_dec_and_test(&doi_def->refcount)) {
-               spin_unlock(&cipso_v4_doi_list_lock);
-               ret_val = -EBUSY;
-               goto doi_remove_return;
-       }
        list_del_rcu(&doi_def->list);
        spin_unlock(&cipso_v4_doi_list_lock);
 
-       cipso_v4_cache_invalidate();
-       call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu);
+       cipso_v4_doi_putdef(doi_def);
        ret_val = 0;
 
 doi_remove_return:
@@ -585,9 +579,6 @@ void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def)
 
        if (!refcount_dec_and_test(&doi_def->refcount))
                return;
-       spin_lock(&cipso_v4_doi_list_lock);
-       list_del_rcu(&doi_def->list);
-       spin_unlock(&cipso_v4_doi_list_lock);
 
        cipso_v4_cache_invalidate();
        call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu);
@@ -1162,7 +1153,7 @@ static void cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
 {
        buf[0] = IPOPT_CIPSO;
        buf[1] = CIPSO_V4_HDR_LEN + len;
-       *(__be32 *)&buf[2] = htonl(doi_def->doi);
+       put_unaligned_be32(doi_def->doi, &buf[2]);
 }
 
 /**
index ff327a6..da21dfc 100644 (file)
@@ -65,7 +65,7 @@ EXPORT_SYMBOL_GPL(inet_peer_base_init);
 #define PEER_MAX_GC 32
 
 /* Exported for sysctl_net_ipv4.  */
-int inet_peer_threshold __read_mostly = 65536 + 128;   /* start to throw entries more
+int inet_peer_threshold __read_mostly; /* start to throw entries more
                                         * aggressively at this stage */
 int inet_peer_minttl __read_mostly = 120 * HZ; /* TTL under high load: 120 sec */
 int inet_peer_maxttl __read_mostly = 10 * 60 * HZ;     /* usual time to live: 10 min */
@@ -73,20 +73,13 @@ int inet_peer_maxttl __read_mostly = 10 * 60 * HZ;  /* usual time to live: 10 min
 /* Called from ip_output.c:ip_init  */
 void __init inet_initpeers(void)
 {
-       struct sysinfo si;
+       u64 nr_entries;
 
-       /* Use the straight interface to information about memory. */
-       si_meminfo(&si);
-       /* The values below were suggested by Alexey Kuznetsov
-        * <kuznet@ms2.inr.ac.ru>.  I don't have any opinion about the values
-        * myself.  --SAW
-        */
-       if (si.totalram <= (32768*1024)/PAGE_SIZE)
-               inet_peer_threshold >>= 1; /* max pool size about 1MB on IA32 */
-       if (si.totalram <= (16384*1024)/PAGE_SIZE)
-               inet_peer_threshold >>= 1; /* about 512KB */
-       if (si.totalram <= (8192*1024)/PAGE_SIZE)
-               inet_peer_threshold >>= 2; /* about 128KB */
+        /* 1% of physical memory */
+       nr_entries = div64_ul((u64)totalram_pages() << PAGE_SHIFT,
+                             100 * L1_CACHE_ALIGN(sizeof(struct inet_peer)));
+
+       inet_peer_threshold = clamp_val(nr_entries, 4096, 65536 + 128);
 
        peer_cachep = kmem_cache_create("inet_peer_cache",
                        sizeof(struct inet_peer),
index 76a420c..f6cc26d 100644 (file)
@@ -502,8 +502,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
                if (!skb_is_gso(skb) &&
                    (inner_iph->frag_off & htons(IP_DF)) &&
                    mtu < pkt_size) {
-                       memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
-                       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
+                       icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
                        return -E2BIG;
                }
        }
@@ -527,7 +526,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
 
                if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU &&
                                        mtu < pkt_size) {
-                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+                       icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                        return -E2BIG;
                }
        }
index abc171e..eb20708 100644 (file)
@@ -238,13 +238,13 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
        if (skb->len > mtu) {
                skb_dst_update_pmtu_no_confirm(skb, mtu);
                if (skb->protocol == htons(ETH_P_IP)) {
-                       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
-                                 htonl(mtu));
+                       icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+                                     htonl(mtu));
                } else {
                        if (mtu < IPV6_MIN_MTU)
                                mtu = IPV6_MIN_MTU;
 
-                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+                       icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                }
 
                dst_release(dst);
index f1c6cbd..743777b 100644 (file)
@@ -1399,7 +1399,7 @@ out:
 
 /* rtnl */
 /* remove all nexthops tied to a device being deleted */
-static void nexthop_flush_dev(struct net_device *dev)
+static void nexthop_flush_dev(struct net_device *dev, unsigned long event)
 {
        unsigned int hash = nh_dev_hashfn(dev->ifindex);
        struct net *net = dev_net(dev);
@@ -1411,6 +1411,10 @@ static void nexthop_flush_dev(struct net_device *dev)
                if (nhi->fib_nhc.nhc_dev != dev)
                        continue;
 
+               if (nhi->reject_nh &&
+                   (event == NETDEV_DOWN || event == NETDEV_CHANGE))
+                       continue;
+
                remove_nexthop(net, nhi->nh_parent, NULL);
        }
 }
@@ -2189,11 +2193,11 @@ static int nh_netdev_event(struct notifier_block *this,
        switch (event) {
        case NETDEV_DOWN:
        case NETDEV_UNREGISTER:
-               nexthop_flush_dev(dev);
+               nexthop_flush_dev(dev, event);
                break;
        case NETDEV_CHANGE:
                if (!(dev_get_flags(dev) & (IFF_RUNNING | IFF_LOWER_UP)))
-                       nexthop_flush_dev(dev);
+                       nexthop_flush_dev(dev, event);
                break;
        case NETDEV_CHANGEMTU:
                info_ext = ptr;
index a3422e4..de7cc84 100644 (file)
@@ -3469,16 +3469,23 @@ static int do_tcp_setsockopt(struct sock *sk, int level, int optname,
                break;
 
        case TCP_QUEUE_SEQ:
-               if (sk->sk_state != TCP_CLOSE)
+               if (sk->sk_state != TCP_CLOSE) {
                        err = -EPERM;
-               else if (tp->repair_queue == TCP_SEND_QUEUE)
-                       WRITE_ONCE(tp->write_seq, val);
-               else if (tp->repair_queue == TCP_RECV_QUEUE) {
-                       WRITE_ONCE(tp->rcv_nxt, val);
-                       WRITE_ONCE(tp->copied_seq, val);
-               }
-               else
+               } else if (tp->repair_queue == TCP_SEND_QUEUE) {
+                       if (!tcp_rtx_queue_empty(sk))
+                               err = -EPERM;
+                       else
+                               WRITE_ONCE(tp->write_seq, val);
+               } else if (tp->repair_queue == TCP_RECV_QUEUE) {
+                       if (tp->rcv_nxt != tp->copied_seq) {
+                               err = -EPERM;
+                       } else {
+                               WRITE_ONCE(tp->rcv_nxt, val);
+                               WRITE_ONCE(tp->copied_seq, val);
+                       }
+               } else {
                        err = -EINVAL;
+               }
                break;
 
        case TCP_REPAIR_OPTIONS:
@@ -4143,7 +4150,8 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
 
                if (get_user(len, optlen))
                        return -EFAULT;
-               if (len < offsetofend(struct tcp_zerocopy_receive, length))
+               if (len < 0 ||
+                   len < offsetofend(struct tcp_zerocopy_receive, length))
                        return -EINVAL;
                if (unlikely(len > sizeof(zc))) {
                        err = check_zeroed_user(optval + sizeof(zc),
index b76c48e..c5b4b58 100644 (file)
@@ -526,7 +526,7 @@ struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb,
        }
 
        if (!sk || NAPI_GRO_CB(skb)->encap_mark ||
-           (skb->ip_summed != CHECKSUM_PARTIAL &&
+           (uh->check && skb->ip_summed != CHECKSUM_PARTIAL &&
             NAPI_GRO_CB(skb)->csum_cnt == 0 &&
             !NAPI_GRO_CB(skb)->csum_valid) ||
            !udp_sk(sk)->gro_receive)
index 51184a7..1578ed9 100644 (file)
@@ -83,6 +83,9 @@ struct calipso_map_cache_entry {
 
 static struct calipso_map_cache_bkt *calipso_cache;
 
+static void calipso_cache_invalidate(void);
+static void calipso_doi_putdef(struct calipso_doi *doi_def);
+
 /* Label Mapping Cache Functions
  */
 
@@ -444,15 +447,10 @@ static int calipso_doi_remove(u32 doi, struct netlbl_audit *audit_info)
                ret_val = -ENOENT;
                goto doi_remove_return;
        }
-       if (!refcount_dec_and_test(&doi_def->refcount)) {
-               spin_unlock(&calipso_doi_list_lock);
-               ret_val = -EBUSY;
-               goto doi_remove_return;
-       }
        list_del_rcu(&doi_def->list);
        spin_unlock(&calipso_doi_list_lock);
 
-       call_rcu(&doi_def->rcu, calipso_doi_free_rcu);
+       calipso_doi_putdef(doi_def);
        ret_val = 0;
 
 doi_remove_return:
@@ -508,10 +506,8 @@ static void calipso_doi_putdef(struct calipso_doi *doi_def)
 
        if (!refcount_dec_and_test(&doi_def->refcount))
                return;
-       spin_lock(&calipso_doi_list_lock);
-       list_del_rcu(&doi_def->list);
-       spin_unlock(&calipso_doi_list_lock);
 
+       calipso_cache_invalidate();
        call_rcu(&doi_def->rcu, calipso_doi_free_rcu);
 }
 
index c3bc89b..1baf43a 100644 (file)
@@ -678,8 +678,8 @@ static int prepare_ip6gre_xmit_ipv6(struct sk_buff *skb,
 
                tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset];
                if (tel->encap_limit == 0) {
-                       icmpv6_send(skb, ICMPV6_PARAMPROB,
-                                   ICMPV6_HDR_FIELD, offset + 2);
+                       icmpv6_ndo_send(skb, ICMPV6_PARAMPROB,
+                                       ICMPV6_HDR_FIELD, offset + 2);
                        return -1;
                }
                *encap_limit = tel->encap_limit - 1;
@@ -805,8 +805,8 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
        if (err != 0) {
                /* XXX: send ICMP error even if DF is not set. */
                if (err == -EMSGSIZE)
-                       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
-                                 htonl(mtu));
+                       icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+                                     htonl(mtu));
                return -1;
        }
 
@@ -837,7 +837,7 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
                          &mtu, skb->protocol);
        if (err != 0) {
                if (err == -EMSGSIZE)
-                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+                       icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                return -1;
        }
 
@@ -1063,10 +1063,10 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
                /* XXX: send ICMP error even if DF is not set. */
                if (err == -EMSGSIZE) {
                        if (skb->protocol == htons(ETH_P_IP))
-                               icmp_send(skb, ICMP_DEST_UNREACH,
-                                         ICMP_FRAG_NEEDED, htonl(mtu));
+                               icmp_ndo_send(skb, ICMP_DEST_UNREACH,
+                                             ICMP_FRAG_NEEDED, htonl(mtu));
                        else
-                               icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+                               icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                }
 
                goto tx_err;
index a7950ba..3fa0eca 100644 (file)
@@ -1332,8 +1332,8 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,
 
                                tel = (void *)&skb_network_header(skb)[offset];
                                if (tel->encap_limit == 0) {
-                                       icmpv6_send(skb, ICMPV6_PARAMPROB,
-                                               ICMPV6_HDR_FIELD, offset + 2);
+                                       icmpv6_ndo_send(skb, ICMPV6_PARAMPROB,
+                                                       ICMPV6_HDR_FIELD, offset + 2);
                                        return -1;
                                }
                                encap_limit = tel->encap_limit - 1;
@@ -1385,11 +1385,11 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,
                if (err == -EMSGSIZE)
                        switch (protocol) {
                        case IPPROTO_IPIP:
-                               icmp_send(skb, ICMP_DEST_UNREACH,
-                                         ICMP_FRAG_NEEDED, htonl(mtu));
+                               icmp_ndo_send(skb, ICMP_DEST_UNREACH,
+                                             ICMP_FRAG_NEEDED, htonl(mtu));
                                break;
                        case IPPROTO_IPV6:
-                               icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+                               icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                                break;
                        default:
                                break;
index 0225fd6..f10e7a7 100644 (file)
@@ -521,10 +521,10 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
                        if (mtu < IPV6_MIN_MTU)
                                mtu = IPV6_MIN_MTU;
 
-                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+                       icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                } else {
-                       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
-                                 htonl(mtu));
+                       icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+                                     htonl(mtu));
                }
 
                err = -EMSGSIZE;
index 9363686..63ccd9f 100644 (file)
@@ -987,7 +987,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                        skb_dst_update_pmtu_no_confirm(skb, mtu);
 
                if (skb->len > mtu && !skb_is_gso(skb)) {
-                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+                       icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                        ip_rt_put(rt);
                        goto tx_error;
                }
index 7be5103..203890e 100644 (file)
@@ -649,9 +649,9 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
        /* Parse and check optional cookie */
        if (session->peer_cookie_len > 0) {
                if (memcmp(ptr, &session->peer_cookie[0], session->peer_cookie_len)) {
-                       pr_warn_ratelimited("%s: cookie mismatch (%u/%u). Discarding.\n",
-                                           tunnel->name, tunnel->tunnel_id,
-                                           session->session_id);
+                       pr_debug_ratelimited("%s: cookie mismatch (%u/%u). Discarding.\n",
+                                            tunnel->name, tunnel->tunnel_id,
+                                            session->session_id);
                        atomic_long_inc(&session->stats.rx_cookie_discards);
                        goto discard;
                }
@@ -702,8 +702,8 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
                 * If user has configured mandatory sequence numbers, discard.
                 */
                if (session->recv_seq) {
-                       pr_warn_ratelimited("%s: recv data has no seq numbers when required. Discarding.\n",
-                                           session->name);
+                       pr_debug_ratelimited("%s: recv data has no seq numbers when required. Discarding.\n",
+                                            session->name);
                        atomic_long_inc(&session->stats.rx_seq_discards);
                        goto discard;
                }
@@ -718,8 +718,8 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
                        session->send_seq = 0;
                        l2tp_session_set_header_len(session, tunnel->version);
                } else if (session->send_seq) {
-                       pr_warn_ratelimited("%s: recv data has no seq numbers when required. Discarding.\n",
-                                           session->name);
+                       pr_debug_ratelimited("%s: recv data has no seq numbers when required. Discarding.\n",
+                                            session->name);
                        atomic_long_inc(&session->stats.rx_seq_discards);
                        goto discard;
                }
@@ -809,9 +809,9 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
 
        /* Short packet? */
        if (!pskb_may_pull(skb, L2TP_HDR_SIZE_MAX)) {
-               pr_warn_ratelimited("%s: recv short packet (len=%d)\n",
-                                   tunnel->name, skb->len);
-               goto error;
+               pr_debug_ratelimited("%s: recv short packet (len=%d)\n",
+                                    tunnel->name, skb->len);
+               goto invalid;
        }
 
        /* Point to L2TP header */
@@ -824,9 +824,9 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
        /* Check protocol version */
        version = hdrflags & L2TP_HDR_VER_MASK;
        if (version != tunnel->version) {
-               pr_warn_ratelimited("%s: recv protocol version mismatch: got %d expected %d\n",
-                                   tunnel->name, version, tunnel->version);
-               goto error;
+               pr_debug_ratelimited("%s: recv protocol version mismatch: got %d expected %d\n",
+                                    tunnel->name, version, tunnel->version);
+               goto invalid;
        }
 
        /* Get length of L2TP packet */
@@ -834,7 +834,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
 
        /* If type is control packet, it is handled by userspace. */
        if (hdrflags & L2TP_HDRFLAG_T)
-               goto error;
+               goto pass;
 
        /* Skip flags */
        ptr += 2;
@@ -863,21 +863,24 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
                        l2tp_session_dec_refcount(session);
 
                /* Not found? Pass to userspace to deal with */
-               pr_warn_ratelimited("%s: no session found (%u/%u). Passing up.\n",
-                                   tunnel->name, tunnel_id, session_id);
-               goto error;
+               pr_debug_ratelimited("%s: no session found (%u/%u). Passing up.\n",
+                                    tunnel->name, tunnel_id, session_id);
+               goto pass;
        }
 
        if (tunnel->version == L2TP_HDR_VER_3 &&
            l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
-               goto error;
+               goto invalid;
 
        l2tp_recv_common(session, skb, ptr, optr, hdrflags, length);
        l2tp_session_dec_refcount(session);
 
        return 0;
 
-error:
+invalid:
+       atomic_long_inc(&tunnel->stats.rx_invalid);
+
+pass:
        /* Put UDP header back */
        __skb_push(skb, sizeof(struct udphdr));
 
index cb21d90..98ea98e 100644 (file)
@@ -39,6 +39,7 @@ struct l2tp_stats {
        atomic_long_t           rx_oos_packets;
        atomic_long_t           rx_errors;
        atomic_long_t           rx_cookie_discards;
+       atomic_long_t           rx_invalid;
 };
 
 struct l2tp_tunnel;
index 83956c9..96eb91b 100644 (file)
@@ -428,6 +428,9 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int fla
                              L2TP_ATTR_STATS_PAD) ||
            nla_put_u64_64bit(skb, L2TP_ATTR_RX_ERRORS,
                              atomic_long_read(&tunnel->stats.rx_errors),
+                             L2TP_ATTR_STATS_PAD) ||
+           nla_put_u64_64bit(skb, L2TP_ATTR_RX_INVALID,
+                             atomic_long_read(&tunnel->stats.rx_invalid),
                              L2TP_ATTR_STATS_PAD))
                goto nla_put_failure;
        nla_nest_end(skb, nest);
@@ -771,6 +774,9 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl
                              L2TP_ATTR_STATS_PAD) ||
            nla_put_u64_64bit(skb, L2TP_ATTR_RX_ERRORS,
                              atomic_long_read(&session->stats.rx_errors),
+                             L2TP_ATTR_STATS_PAD) ||
+           nla_put_u64_64bit(skb, L2TP_ATTR_RX_INVALID,
+                             atomic_long_read(&session->stats.rx_invalid),
                              L2TP_ATTR_STATS_PAD))
                goto nla_put_failure;
        nla_nest_end(skb, nest);
index b169014..1482259 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/netdev_features.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
+#include <net/mpls.h>
 
 static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
                                       netdev_features_t features)
@@ -27,6 +28,8 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
 
        skb_reset_network_header(skb);
        mpls_hlen = skb_inner_network_header(skb) - skb_network_header(skb);
+       if (unlikely(!mpls_hlen || mpls_hlen % MPLS_HLEN))
+               goto out;
        if (unlikely(!pskb_may_pull(skb, mpls_hlen)))
                goto out;
 
index c5d5e68..7695857 100644 (file)
@@ -1061,6 +1061,12 @@ out:
        }
 }
 
+static void __mptcp_clean_una_wakeup(struct sock *sk)
+{
+       __mptcp_clean_una(sk);
+       mptcp_write_space(sk);
+}
+
 static void mptcp_enter_memory_pressure(struct sock *sk)
 {
        struct mptcp_subflow_context *subflow;
@@ -1189,6 +1195,7 @@ static bool mptcp_tx_cache_refill(struct sock *sk, int size,
                         */
                        while (skbs->qlen > 1) {
                                skb = __skb_dequeue_tail(skbs);
+                               *total_ts -= skb->truesize;
                                __kfree_skb(skb);
                        }
                        return skbs->qlen > 0;
@@ -1444,7 +1451,7 @@ static void mptcp_push_release(struct sock *sk, struct sock *ssk,
        release_sock(ssk);
 }
 
-static void mptcp_push_pending(struct sock *sk, unsigned int flags)
+static void __mptcp_push_pending(struct sock *sk, unsigned int flags)
 {
        struct sock *prev_ssk = NULL, *ssk = NULL;
        struct mptcp_sock *msk = mptcp_sk(sk);
@@ -1696,14 +1703,14 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
 wait_for_memory:
                mptcp_set_nospace(sk);
-               mptcp_push_pending(sk, msg->msg_flags);
+               __mptcp_push_pending(sk, msg->msg_flags);
                ret = sk_stream_wait_memory(sk, &timeo);
                if (ret)
                        goto out;
        }
 
        if (copied)
-               mptcp_push_pending(sk, msg->msg_flags);
+               __mptcp_push_pending(sk, msg->msg_flags);
 
 out:
        release_sock(sk);
@@ -2115,6 +2122,14 @@ static struct sock *mptcp_subflow_get_retrans(const struct mptcp_sock *msk)
        return backup;
 }
 
+static void mptcp_dispose_initial_subflow(struct mptcp_sock *msk)
+{
+       if (msk->subflow) {
+               iput(SOCK_INODE(msk->subflow));
+               msk->subflow = NULL;
+       }
+}
+
 /* subflow sockets can be either outgoing (connect) or incoming
  * (accept).
  *
@@ -2126,6 +2141,8 @@ static struct sock *mptcp_subflow_get_retrans(const struct mptcp_sock *msk)
 static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
                              struct mptcp_subflow_context *subflow)
 {
+       struct mptcp_sock *msk = mptcp_sk(sk);
+
        list_del(&subflow->node);
 
        lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
@@ -2154,6 +2171,18 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
        release_sock(ssk);
 
        sock_put(ssk);
+
+       if (ssk == msk->last_snd)
+               msk->last_snd = NULL;
+
+       if (ssk == msk->ack_hint)
+               msk->ack_hint = NULL;
+
+       if (ssk == msk->first)
+               msk->first = NULL;
+
+       if (msk->subflow && ssk == msk->subflow->sk)
+               mptcp_dispose_initial_subflow(msk);
 }
 
 void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
@@ -2238,14 +2267,58 @@ static void mptcp_check_fastclose(struct mptcp_sock *msk)
        mptcp_close_wake_up(sk);
 }
 
-static void mptcp_worker(struct work_struct *work)
+static void __mptcp_retrans(struct sock *sk)
 {
-       struct mptcp_sock *msk = container_of(work, struct mptcp_sock, work);
-       struct sock *ssk, *sk = &msk->sk.icsk_inet.sk;
+       struct mptcp_sock *msk = mptcp_sk(sk);
        struct mptcp_sendmsg_info info = {};
        struct mptcp_data_frag *dfrag;
        size_t copied = 0;
-       int state, ret;
+       struct sock *ssk;
+       int ret;
+
+       __mptcp_clean_una_wakeup(sk);
+       dfrag = mptcp_rtx_head(sk);
+       if (!dfrag)
+               return;
+
+       ssk = mptcp_subflow_get_retrans(msk);
+       if (!ssk)
+               goto reset_timer;
+
+       lock_sock(ssk);
+
+       /* limit retransmission to the bytes already sent on some subflows */
+       info.sent = 0;
+       info.limit = dfrag->already_sent;
+       while (info.sent < dfrag->already_sent) {
+               if (!mptcp_alloc_tx_skb(sk, ssk))
+                       break;
+
+               ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
+               if (ret <= 0)
+                       break;
+
+               MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RETRANSSEGS);
+               copied += ret;
+               info.sent += ret;
+       }
+       if (copied)
+               tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle,
+                        info.size_goal);
+
+       mptcp_set_timeout(sk, ssk);
+       release_sock(ssk);
+
+reset_timer:
+       if (!mptcp_timer_pending(sk))
+               mptcp_reset_timer(sk);
+}
+
+static void mptcp_worker(struct work_struct *work)
+{
+       struct mptcp_sock *msk = container_of(work, struct mptcp_sock, work);
+       struct sock *sk = &msk->sk.icsk_inet.sk;
+       int state;
 
        lock_sock(sk);
        state = sk->sk_state;
@@ -2280,45 +2353,8 @@ static void mptcp_worker(struct work_struct *work)
        if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
                __mptcp_close_subflow(msk);
 
-       if (!test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags))
-               goto unlock;
-
-       __mptcp_clean_una(sk);
-       dfrag = mptcp_rtx_head(sk);
-       if (!dfrag)
-               goto unlock;
-
-       ssk = mptcp_subflow_get_retrans(msk);
-       if (!ssk)
-               goto reset_unlock;
-
-       lock_sock(ssk);
-
-       /* limit retransmission to the bytes already sent on some subflows */
-       info.sent = 0;
-       info.limit = dfrag->already_sent;
-       while (info.sent < dfrag->already_sent) {
-               if (!mptcp_alloc_tx_skb(sk, ssk))
-                       break;
-
-               ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
-               if (ret <= 0)
-                       break;
-
-               MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RETRANSSEGS);
-               copied += ret;
-               info.sent += ret;
-       }
-       if (copied)
-               tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle,
-                        info.size_goal);
-
-       mptcp_set_timeout(sk, ssk);
-       release_sock(ssk);
-
-reset_unlock:
-       if (!mptcp_timer_pending(sk))
-               mptcp_reset_timer(sk);
+       if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags))
+               __mptcp_retrans(sk);
 
 unlock:
        release_sock(sk);
@@ -2523,12 +2559,6 @@ static void __mptcp_destroy_sock(struct sock *sk)
 
        might_sleep();
 
-       /* dispose the ancillatory tcp socket, if any */
-       if (msk->subflow) {
-               iput(SOCK_INODE(msk->subflow));
-               msk->subflow = NULL;
-       }
-
        /* be sure to always acquire the join list lock, to sync vs
         * mptcp_finish_join().
         */
@@ -2553,6 +2583,7 @@ static void __mptcp_destroy_sock(struct sock *sk)
        sk_stream_kill_queues(sk);
        xfrm_sk_free_policy(sk);
        sk_refcnt_debug_release(sk);
+       mptcp_dispose_initial_subflow(msk);
        sock_put(sk);
 }
 
@@ -2934,13 +2965,14 @@ static void mptcp_release_cb(struct sock *sk)
 {
        unsigned long flags, nflags;
 
-       /* push_pending may touch wmem_reserved, do it before the later
-        * cleanup
-        */
-       if (test_and_clear_bit(MPTCP_CLEAN_UNA, &mptcp_sk(sk)->flags))
-               __mptcp_clean_una(sk);
-       if (test_and_clear_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags)) {
-               /* mptcp_push_pending() acquires the subflow socket lock
+       for (;;) {
+               flags = 0;
+               if (test_and_clear_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags))
+                       flags |= MPTCP_PUSH_PENDING;
+               if (!flags)
+                       break;
+
+               /* the following actions acquire the subflow socket lock
                 *
                 * 1) can't be invoked in atomic scope
                 * 2) must avoid ABBA deadlock with msk socket spinlock: the RX
@@ -2949,13 +2981,21 @@ static void mptcp_release_cb(struct sock *sk)
                 */
 
                spin_unlock_bh(&sk->sk_lock.slock);
-               mptcp_push_pending(sk, 0);
+               if (flags & MPTCP_PUSH_PENDING)
+                       __mptcp_push_pending(sk, 0);
+
+               cond_resched();
                spin_lock_bh(&sk->sk_lock.slock);
        }
+
+       if (test_and_clear_bit(MPTCP_CLEAN_UNA, &mptcp_sk(sk)->flags))
+               __mptcp_clean_una_wakeup(sk);
        if (test_and_clear_bit(MPTCP_ERROR_REPORT, &mptcp_sk(sk)->flags))
                __mptcp_error_report(sk);
 
-       /* clear any wmem reservation and errors */
+       /* push_pending may touch wmem_reserved, ensure we do the cleanup
+        * later
+        */
        __mptcp_update_wmem(sk);
        __mptcp_update_rmem(sk);
 
@@ -3285,6 +3325,9 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
                /* PM/worker can now acquire the first subflow socket
                 * lock without racing with listener queue cleanup,
                 * we can notify it, if needed.
+                *
+                * Even if remote has reset the initial subflow by now
+                * the refcnt is still at least one.
                 */
                subflow = mptcp_subflow_ctx(msk->first);
                list_add(&subflow->node, &msk->conn_list);
index 91827d9..e21a5bc 100644 (file)
 #define TCPOLEN_MPTCP_DSS_MAP64                14
 #define TCPOLEN_MPTCP_DSS_CHECKSUM     2
 #define TCPOLEN_MPTCP_ADD_ADDR         16
-#define TCPOLEN_MPTCP_ADD_ADDR_PORT    20
+#define TCPOLEN_MPTCP_ADD_ADDR_PORT    18
 #define TCPOLEN_MPTCP_ADD_ADDR_BASE    8
-#define TCPOLEN_MPTCP_ADD_ADDR_BASE_PORT       12
+#define TCPOLEN_MPTCP_ADD_ADDR_BASE_PORT       10
 #define TCPOLEN_MPTCP_ADD_ADDR6                28
-#define TCPOLEN_MPTCP_ADD_ADDR6_PORT   32
+#define TCPOLEN_MPTCP_ADD_ADDR6_PORT   30
 #define TCPOLEN_MPTCP_ADD_ADDR6_BASE   20
-#define TCPOLEN_MPTCP_ADD_ADDR6_BASE_PORT      24
-#define TCPOLEN_MPTCP_PORT_LEN         4
+#define TCPOLEN_MPTCP_ADD_ADDR6_BASE_PORT      22
+#define TCPOLEN_MPTCP_PORT_LEN         2
+#define TCPOLEN_MPTCP_PORT_ALIGN       2
 #define TCPOLEN_MPTCP_RM_ADDR_BASE     4
 #define TCPOLEN_MPTCP_PRIO             3
 #define TCPOLEN_MPTCP_PRIO_ALIGN       4
@@ -701,8 +702,9 @@ static inline unsigned int mptcp_add_addr_len(int family, bool echo, bool port)
                len = TCPOLEN_MPTCP_ADD_ADDR6_BASE;
        if (!echo)
                len += MPTCPOPT_THMAC_LEN;
+       /* account for 2 trailing 'nop' options */
        if (port)
-               len += TCPOLEN_MPTCP_PORT_LEN;
+               len += TCPOLEN_MPTCP_PORT_LEN + TCPOLEN_MPTCP_PORT_ALIGN;
 
        return len;
 }
index e1fbcab..3d47d67 100644 (file)
@@ -687,11 +687,6 @@ create_child:
                        /* move the msk reference ownership to the subflow */
                        subflow_req->msk = NULL;
                        ctx->conn = (struct sock *)owner;
-                       if (!mptcp_finish_join(child))
-                               goto dispose_child;
-
-                       SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKRX);
-                       tcp_rsk(req)->drop_req = true;
 
                        if (subflow_use_different_sport(owner, sk)) {
                                pr_debug("ack inet_sport=%d %d",
@@ -699,10 +694,16 @@ create_child:
                                         ntohs(inet_sk((struct sock *)owner)->inet_sport));
                                if (!mptcp_pm_sport_in_anno_list(owner, sk)) {
                                        SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MISMATCHPORTACKRX);
-                                       goto out;
+                                       goto dispose_child;
                                }
                                SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINPORTACKRX);
                        }
+
+                       if (!mptcp_finish_join(child))
+                               goto dispose_child;
+
+                       SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKRX);
+                       tcp_rsk(req)->drop_req = true;
                }
        }
 
@@ -1297,6 +1298,7 @@ failed_unlink:
        spin_lock_bh(&msk->join_list_lock);
        list_del(&subflow->node);
        spin_unlock_bh(&msk->join_list_lock);
+       sock_put(mptcp_subflow_tcp_sock(subflow));
 
 failed:
        subflow->disposable = 1;
index 118f415..b055187 100644 (file)
@@ -219,7 +219,7 @@ nf_ct_lookup_helper(struct nf_conn *ct, struct net *net)
                        return NULL;
                pr_info("nf_conntrack: default automatic helper assignment "
                        "has been turned off for security reasons and CT-based "
-                       " firewall rule not found. Use the iptables CT target "
+                       "firewall rule not found. Use the iptables CT target "
                        "to attach helpers instead.\n");
                net->ct.auto_assign_helper_warned = 1;
                return NULL;
@@ -228,7 +228,6 @@ nf_ct_lookup_helper(struct nf_conn *ct, struct net *net)
        return __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
 }
 
-
 int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
                              gfp_t flags)
 {
index 1d7e1c5..ec23330 100644 (file)
@@ -982,8 +982,10 @@ int nf_conntrack_tcp_packet(struct nf_conn *ct,
                                        IP_CT_EXP_CHALLENGE_ACK;
                }
                spin_unlock_bh(&ct->lock);
-               nf_ct_l4proto_log_invalid(skb, ct, "invalid packet ignored in "
-                                         "state %s ", tcp_conntrack_names[old_state]);
+               nf_ct_l4proto_log_invalid(skb, ct,
+                                         "packet (index %d) in dir %d ignored, state %s",
+                                         index, dir,
+                                         tcp_conntrack_names[old_state]);
                return NF_ACCEPT;
        case TCP_CONNTRACK_MAX:
                /* Special case for SYN proxy: when the SYN to the server or
index e87b6bd..4731d21 100644 (file)
@@ -646,8 +646,8 @@ nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,
 }
 
 static unsigned int
-nf_nat_ipv4_in(void *priv, struct sk_buff *skb,
-              const struct nf_hook_state *state)
+nf_nat_ipv4_pre_routing(void *priv, struct sk_buff *skb,
+                       const struct nf_hook_state *state)
 {
        unsigned int ret;
        __be32 daddr = ip_hdr(skb)->daddr;
@@ -659,6 +659,23 @@ nf_nat_ipv4_in(void *priv, struct sk_buff *skb,
        return ret;
 }
 
+static unsigned int
+nf_nat_ipv4_local_in(void *priv, struct sk_buff *skb,
+                    const struct nf_hook_state *state)
+{
+       __be32 saddr = ip_hdr(skb)->saddr;
+       struct sock *sk = skb->sk;
+       unsigned int ret;
+
+       ret = nf_nat_ipv4_fn(priv, skb, state);
+
+       if (ret == NF_ACCEPT && sk && saddr != ip_hdr(skb)->saddr &&
+           !inet_sk_transparent(sk))
+               skb_orphan(skb); /* TCP edemux obtained wrong socket */
+
+       return ret;
+}
+
 static unsigned int
 nf_nat_ipv4_out(void *priv, struct sk_buff *skb,
                const struct nf_hook_state *state)
@@ -736,7 +753,7 @@ nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,
 static const struct nf_hook_ops nf_nat_ipv4_ops[] = {
        /* Before packet filtering, change destination */
        {
-               .hook           = nf_nat_ipv4_in,
+               .hook           = nf_nat_ipv4_pre_routing,
                .pf             = NFPROTO_IPV4,
                .hooknum        = NF_INET_PRE_ROUTING,
                .priority       = NF_IP_PRI_NAT_DST,
@@ -757,7 +774,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = {
        },
        /* After packet filtering, change source */
        {
-               .hook           = nf_nat_ipv4_fn,
+               .hook           = nf_nat_ipv4_local_in,
                .pf             = NFPROTO_IPV4,
                .hooknum        = NF_INET_LOCAL_IN,
                .priority       = NF_IP_PRI_NAT_SRC,
index c1eb5cd..224c8e5 100644 (file)
@@ -916,6 +916,12 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
        if (flags == ctx->table->flags)
                return 0;
 
+       if ((nft_table_has_owner(ctx->table) &&
+            !(flags & NFT_TABLE_F_OWNER)) ||
+           (!nft_table_has_owner(ctx->table) &&
+            flags & NFT_TABLE_F_OWNER))
+               return -EOPNOTSUPP;
+
        trans = nft_trans_alloc(ctx, NFT_MSG_NEWTABLE,
                                sizeof(struct nft_trans_table));
        if (trans == NULL)
@@ -9022,8 +9028,12 @@ static void __nft_release_hooks(struct net *net)
 {
        struct nft_table *table;
 
-       list_for_each_entry(table, &net->nft.tables, list)
+       list_for_each_entry(table, &net->nft.tables, list) {
+               if (nft_table_has_owner(table))
+                       continue;
+
                __nft_release_hook(net, table);
+       }
 }
 
 static void __nft_release_table(struct net *net, struct nft_table *table)
@@ -9073,13 +9083,12 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
        nf_tables_table_destroy(&ctx);
 }
 
-static void __nft_release_tables(struct net *net, u32 nlpid)
+static void __nft_release_tables(struct net *net)
 {
        struct nft_table *table, *nt;
 
        list_for_each_entry_safe(table, nt, &net->nft.tables, list) {
-               if (nft_table_has_owner(table) &&
-                   nlpid != table->nlpid)
+               if (nft_table_has_owner(table))
                        continue;
 
                __nft_release_table(net, table);
@@ -9145,7 +9154,7 @@ static void __net_exit nf_tables_exit_net(struct net *net)
        mutex_lock(&net->nft.commit_mutex);
        if (!list_empty(&net->nft.commit_list))
                __nf_tables_abort(net, NFNL_ABORT_NONE);
-       __nft_release_tables(net, 0);
+       __nft_release_tables(net);
        mutex_unlock(&net->nft.commit_mutex);
        WARN_ON_ONCE(!list_empty(&net->nft.tables));
        WARN_ON_ONCE(!list_empty(&net->nft.module_list));
index acce622..bce6ca2 100644 (file)
@@ -330,6 +330,7 @@ static int match_revfn(u8 af, const char *name, u8 revision, int *bestp)
        const struct xt_match *m;
        int have_rev = 0;
 
+       mutex_lock(&xt[af].mutex);
        list_for_each_entry(m, &xt[af].match, list) {
                if (strcmp(m->name, name) == 0) {
                        if (m->revision > *bestp)
@@ -338,6 +339,7 @@ static int match_revfn(u8 af, const char *name, u8 revision, int *bestp)
                                have_rev = 1;
                }
        }
+       mutex_unlock(&xt[af].mutex);
 
        if (af != NFPROTO_UNSPEC && !have_rev)
                return match_revfn(NFPROTO_UNSPEC, name, revision, bestp);
@@ -350,6 +352,7 @@ static int target_revfn(u8 af, const char *name, u8 revision, int *bestp)
        const struct xt_target *t;
        int have_rev = 0;
 
+       mutex_lock(&xt[af].mutex);
        list_for_each_entry(t, &xt[af].target, list) {
                if (strcmp(t->name, name) == 0) {
                        if (t->revision > *bestp)
@@ -358,6 +361,7 @@ static int target_revfn(u8 af, const char *name, u8 revision, int *bestp)
                                have_rev = 1;
                }
        }
+       mutex_unlock(&xt[af].mutex);
 
        if (af != NFPROTO_UNSPEC && !have_rev)
                return target_revfn(NFPROTO_UNSPEC, name, revision, bestp);
@@ -371,12 +375,10 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target,
 {
        int have_rev, best = -1;
 
-       mutex_lock(&xt[af].mutex);
        if (target == 1)
                have_rev = target_revfn(af, name, revision, &best);
        else
                have_rev = match_revfn(af, name, revision, &best);
-       mutex_unlock(&xt[af].mutex);
 
        /* Nothing at all?  Return 0 to try loading module. */
        if (best == -1) {
index 726dda9..4f50a64 100644 (file)
@@ -575,6 +575,7 @@ list_start:
 
                break;
        }
+       cipso_v4_doi_putdef(doi_def);
        rcu_read_unlock();
 
        genlmsg_end(ans_skb, data);
@@ -583,12 +584,14 @@ list_start:
 list_retry:
        /* XXX - this limit is a guesstimate */
        if (nlsze_mult < 4) {
+               cipso_v4_doi_putdef(doi_def);
                rcu_read_unlock();
                kfree_skb(ans_skb);
                nlsze_mult *= 2;
                goto list_start;
        }
 list_failure_lock:
+       cipso_v4_doi_putdef(doi_def);
        rcu_read_unlock();
 list_failure:
        kfree_skb(ans_skb);
index b343582..edb6ac1 100644 (file)
@@ -439,7 +439,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
        if (len == 0 || len & 3)
                return -EINVAL;
 
-       skb = netdev_alloc_skb(NULL, len);
+       skb = __netdev_alloc_skb(NULL, len, GFP_ATOMIC | __GFP_NOWARN);
        if (!skb)
                return -ENOMEM;
 
@@ -958,8 +958,10 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
        plen = (len + 3) & ~3;
        skb = sock_alloc_send_skb(sk, plen + QRTR_HDR_MAX_SIZE,
                                  msg->msg_flags & MSG_DONTWAIT, &rc);
-       if (!skb)
+       if (!skb) {
+               rc = -ENOMEM;
                goto out_node;
+       }
 
        skb_reserve(skb, QRTR_HDR_MAX_SIZE);
 
index e2e4353..f87d077 100644 (file)
@@ -2168,7 +2168,7 @@ static int tc_dump_tclass_qdisc(struct Qdisc *q, struct sk_buff *skb,
 
 static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb,
                               struct tcmsg *tcm, struct netlink_callback *cb,
-                              int *t_p, int s_t)
+                              int *t_p, int s_t, bool recur)
 {
        struct Qdisc *q;
        int b;
@@ -2179,7 +2179,7 @@ static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb,
        if (tc_dump_tclass_qdisc(root, skb, tcm, cb, t_p, s_t) < 0)
                return -1;
 
-       if (!qdisc_dev(root))
+       if (!qdisc_dev(root) || !recur)
                return 0;
 
        if (tcm->tcm_parent) {
@@ -2214,13 +2214,13 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
        s_t = cb->args[0];
        t = 0;
 
-       if (tc_dump_tclass_root(dev->qdisc, skb, tcm, cb, &t, s_t) < 0)
+       if (tc_dump_tclass_root(dev->qdisc, skb, tcm, cb, &t, s_t, true) < 0)
                goto done;
 
        dev_queue = dev_ingress_queue(dev);
        if (dev_queue &&
            tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb,
-                               &t, s_t) < 0)
+                               &t, s_t, false) < 0)
                goto done;
 
 done:
index a9c6af5..5ba4567 100644 (file)
@@ -75,7 +75,7 @@ int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn)
                return 1;
 
        /* Verify that we can hold this TSN and that it will not
-        * overlfow our map
+        * overflow our map
         */
        if (!TSN_lt(tsn, map->base_tsn + SCTP_TSN_MAP_SIZE))
                return -1;
index db0cb73..1e2a110 100644 (file)
@@ -1699,5 +1699,7 @@ int main(int argc, char **argv)
 
        xdpsock_cleanup();
 
+       munmap(bufs, NUM_FRAMES * opt_xsk_frame_size);
+
        return 0;
 }
index 7409d78..80d966c 100644 (file)
@@ -260,6 +260,11 @@ static struct btf_id *add_symbol(struct rb_root *root, char *name, size_t size)
        return btf_id__add(root, id, false);
 }
 
+/* Older libelf.h and glibc elf.h might not yet define the ELF compression types. */
+#ifndef SHF_COMPRESSED
+#define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */
+#endif
+
 /*
  * The data of compressed section should be aligned to 4
  * (for 32bit) or 8 (for 64 bit) bytes. The binutils ld
index 4c24daa..79c8933 100644 (file)
@@ -3850,7 +3850,6 @@ union bpf_attr {
  *
  * long bpf_check_mtu(void *ctx, u32 ifindex, u32 *mtu_len, s32 len_diff, u64 flags)
  *     Description
-
  *             Check ctx packet size against exceeding MTU of net device (based
  *             on *ifindex*).  This helper will likely be used in combination
  *             with helpers that adjust/change the packet size.
index ffbb588..526fc35 100644 (file)
@@ -610,15 +610,16 @@ static int xsk_lookup_bpf_maps(struct xsk_socket *xsk)
                if (fd < 0)
                        continue;
 
+               memset(&map_info, 0, map_len);
                err = bpf_obj_get_info_by_fd(fd, &map_info, &map_len);
                if (err) {
                        close(fd);
                        continue;
                }
 
-               if (!strcmp(map_info.name, "xsks_map")) {
+               if (!strncmp(map_info.name, "xsks_map", sizeof(map_info.name))) {
                        ctx->xsks_map_fd = fd;
-                       continue;
+                       break;
                }
 
                close(fd);
index 6b67003..1d8918d 100644 (file)
@@ -16,6 +16,13 @@ bool skip = false;
 #define STRSIZE                        2048
 #define EXPECTED_STRSIZE       256
 
+#if defined(bpf_target_s390)
+/* NULL points to a readable struct lowcore on s390, so take the last page */
+#define BADPTR                 ((void *)0xFFFFFFFFFFFFF000ULL)
+#else
+#define BADPTR                 0
+#endif
+
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(x)  (sizeof(x) / sizeof((x)[0]))
 #endif
@@ -113,11 +120,11 @@ int BPF_PROG(trace_netif_receive_skb, struct sk_buff *skb)
        }
 
        /* Check invalid ptr value */
-       p.ptr = 0;
+       p.ptr = BADPTR;
        __ret = bpf_snprintf_btf(str, STRSIZE, &p, sizeof(p), 0);
        if (__ret >= 0) {
-               bpf_printk("printing NULL should generate error, got (%d)",
-                          __ret);
+               bpf_printk("printing %llx should generate error, got (%d)",
+                          (unsigned long long)BADPTR, __ret);
                ret = -ERANGE;
        }
 
index 2848804..ef5277d 100644 (file)
@@ -15,5 +15,5 @@ __noinline int foo(const struct S *s)
 SEC("cgroup_skb/ingress")
 int test_cls(struct __sk_buff *skb)
 {
-       return foo(skb);
+       return foo((const void *)skb);
 }
index a621b58..9afe947 100644 (file)
@@ -446,10 +446,8 @@ int _geneve_get_tunnel(struct __sk_buff *skb)
        }
 
        ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
-       if (ret < 0) {
-               ERROR(ret);
-               return TC_ACT_SHOT;
-       }
+       if (ret < 0)
+               gopt.opt_class = 0;
 
        bpf_trace_printk(fmt, sizeof(fmt),
                        key.tunnel_id, key.remote_ipv4, gopt.opt_class);
index bed53b5..1b138cd 100644 (file)
        BPF_MOV64_IMM(BPF_REG_5, 0),
        BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
                     BPF_FUNC_csum_diff),
+       BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffff),
        BPF_EXIT_INSN(),
        },
        .prog_type = BPF_PROG_TYPE_SCHED_CLS,
        .fixup_map_array_ro = { 3 },
        .result = ACCEPT,
-       .retval = -29,
+       .retval = 65507,
 },
 {
        "invalid write map access into a read-only array 1",
index 1bdc8e6..fe4bb70 100644 (file)
        },
        .result = ACCEPT,
 },
+{
+       "BPF_ATOMIC_AND with fetch - r0 as source reg",
+       .insns = {
+               /* val = 0x110; */
+               BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0x110),
+               /* old = atomic_fetch_and(&val, 0x011); */
+               BPF_MOV64_IMM(BPF_REG_0, 0x011),
+               BPF_ATOMIC_OP(BPF_DW, BPF_AND | BPF_FETCH, BPF_REG_10, BPF_REG_0, -8),
+               /* if (old != 0x110) exit(3); */
+               BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0x110, 2),
+               BPF_MOV64_IMM(BPF_REG_0, 3),
+               BPF_EXIT_INSN(),
+               /* if (val != 0x010) exit(2); */
+               BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -8),
+               BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x010, 2),
+               BPF_MOV64_IMM(BPF_REG_1, 2),
+               BPF_EXIT_INSN(),
+               /* exit(0); */
+               BPF_MOV64_IMM(BPF_REG_0, 0),
+               BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+},
index 2efd8bc..6e52dfc 100644 (file)
        .result = REJECT,
        .errstr = "invalid read from stack",
 },
+{
+       "BPF_W cmpxchg should zero top 32 bits",
+       .insns = {
+               /* r0 = U64_MAX; */
+               BPF_MOV64_IMM(BPF_REG_0, 0),
+               BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 1),
+               /* u64 val = r0; */
+               BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
+               /* r0 = (u32)atomic_cmpxchg((u32 *)&val, r0, 1); */
+               BPF_MOV32_IMM(BPF_REG_1, 1),
+               BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
+               /* r1 = 0x00000000FFFFFFFFull; */
+               BPF_MOV64_IMM(BPF_REG_1, 1),
+               BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
+               BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
+               /* if (r0 != r1) exit(1); */
+               BPF_JMP_REG(BPF_JEQ, BPF_REG_0, BPF_REG_1, 2),
+               BPF_MOV32_IMM(BPF_REG_0, 1),
+               BPF_EXIT_INSN(),
+               /* exit(0); */
+               BPF_MOV32_IMM(BPF_REG_0, 0),
+               BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+},
index 70f982e..9d0716a 100644 (file)
        },
        .result = ACCEPT,
 },
+{
+       "BPF_W atomic_fetch_or should zero top 32 bits",
+       .insns = {
+               /* r1 = U64_MAX; */
+               BPF_MOV64_IMM(BPF_REG_1, 0),
+               BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
+               /* u64 val = r1; */
+               BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+               /* r1 = (u32)atomic_fetch_or((u32 *)&val, 2); */
+               BPF_MOV32_IMM(BPF_REG_1, 2),
+               BPF_ATOMIC_OP(BPF_W, BPF_OR | BPF_FETCH, BPF_REG_10, BPF_REG_1, -8),
+               /* r2 = 0x00000000FFFFFFFF; */
+               BPF_MOV64_IMM(BPF_REG_2, 1),
+               BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 32),
+               BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 1),
+               /* if (r2 != r1) exit(1); */
+               BPF_JMP_REG(BPF_JEQ, BPF_REG_2, BPF_REG_1, 2),
+               BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
+               BPF_EXIT_INSN(),
+               /* exit(0); */
+               BPF_MOV32_IMM(BPF_REG_0, 0),
+               BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+},
index 4c7d336..d98fb85 100755 (executable)
@@ -1524,6 +1524,14 @@ basic()
        run_cmd "$IP nexthop replace id 2 blackhole dev veth1"
        log_test $? 2 "Blackhole nexthop with other attributes"
 
+       # blackhole nexthop should not be affected by the state of the loopback
+       # device
+       run_cmd "$IP link set dev lo down"
+       check_nexthop "id 2" "id 2 blackhole"
+       log_test $? 0 "Blackhole nexthop with loopback device down"
+
+       run_cmd "$IP link set dev lo up"
+
        #
        # groups
        #
index 197e769..f8cda82 100755 (executable)
@@ -86,11 +86,20 @@ test_ip6gretap()
 
 test_gretap_stp()
 {
+       # Sometimes after mirror installation, the neighbor's state is not valid.
+       # The reason is that there is no SW datapath activity related to the
+       # neighbor for the remote GRE address. Therefore whether the corresponding
+       # neighbor will be valid is a matter of luck, and the test is thus racy.
+       # Set the neighbor's state to permanent, so it would be always valid.
+       ip neigh replace 192.0.2.130 lladdr $(mac_get $h3) \
+               nud permanent dev br2
        full_test_span_gre_stp gt4 $swp3.555 "mirror to gretap"
 }
 
 test_ip6gretap_stp()
 {
+       ip neigh replace 2001:db8:2::2 lladdr $(mac_get $h3) \
+               nud permanent dev br2
        full_test_span_gre_stp gt6 $swp3.555 "mirror to ip6gretap"
 }
 
index 17ced7d..f23438d 100644 (file)
@@ -1785,7 +1785,7 @@ static void grand_child_serv(unsigned int nr, int cmd_fd, void *buf,
                break;
        default:
                printk("got unknown msg type %d", msg->type);
-       };
+       }
 }
 
 static int grand_child_f(unsigned int nr, int cmd_fd, void *buf)
index 3006a8e..3171069 100644 (file)
@@ -4,7 +4,7 @@
 TEST_PROGS := nft_trans_stress.sh nft_nat.sh bridge_brouter.sh \
        conntrack_icmp_related.sh nft_flowtable.sh ipvs.sh \
        nft_concat_range.sh nft_conntrack_helper.sh \
-       nft_queue.sh nft_meta.sh \
+       nft_queue.sh nft_meta.sh nf_nat_edemux.sh \
        ipip-conntrack-mtu.sh
 
 LDLIBS = -lmnl
diff --git a/tools/testing/selftests/netfilter/nf_nat_edemux.sh b/tools/testing/selftests/netfilter/nf_nat_edemux.sh
new file mode 100755 (executable)
index 0000000..cfee3b6
--- /dev/null
@@ -0,0 +1,99 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test NAT source port clash resolution
+#
+
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+ret=0
+
+sfx=$(mktemp -u "XXXXXXXX")
+ns1="ns1-$sfx"
+ns2="ns2-$sfx"
+
+cleanup()
+{
+       ip netns del $ns1
+       ip netns del $ns2
+}
+
+iperf3 -v > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without iperf3"
+       exit $ksft_skip
+fi
+
+iptables --version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without iptables"
+       exit $ksft_skip
+fi
+
+ip -Version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without ip tool"
+       exit $ksft_skip
+fi
+
+ip netns add "$ns1"
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not create net namespace $ns1"
+       exit $ksft_skip
+fi
+
+trap cleanup EXIT
+
+ip netns add $ns2
+
+# Connect the namespaces using a veth pair
+ip link add name veth2 type veth peer name veth1
+ip link set netns $ns1 dev veth1
+ip link set netns $ns2 dev veth2
+
+ip netns exec $ns1 ip link set up dev lo
+ip netns exec $ns1 ip link set up dev veth1
+ip netns exec $ns1 ip addr add 192.168.1.1/24 dev veth1
+
+ip netns exec $ns2 ip link set up dev lo
+ip netns exec $ns2 ip link set up dev veth2
+ip netns exec $ns2 ip addr add 192.168.1.2/24 dev veth2
+
+# Create a server in one namespace
+ip netns exec $ns1 iperf3 -s > /dev/null 2>&1 &
+iperfs=$!
+
+# Restrict source port to just one so we don't have to exhaust
+# all others.
+ip netns exec $ns2 sysctl -q net.ipv4.ip_local_port_range="10000 10000"
+
+# add a virtual IP using DNAT
+ip netns exec $ns2 iptables -t nat -A OUTPUT -d 10.96.0.1/32 -p tcp --dport 443 -j DNAT --to-destination 192.168.1.1:5201
+
+# ... and route it to the other namespace
+ip netns exec $ns2 ip route add 10.96.0.1 via 192.168.1.1
+
+sleep 1
+
+# add a persistent connection from the other namespace
+ip netns exec $ns2 nc -q 10 -w 10 192.168.1.1 5201 > /dev/null &
+
+sleep 1
+
+# ip daddr:dport will be rewritten to 192.168.1.1 5201
+# NAT must reallocate source port 10000 because
+# 192.168.1.2:10000 -> 192.168.1.1:5201 is already in use
+echo test | ip netns exec $ns2 nc -w 3 -q 3 10.96.0.1 443 >/dev/null
+ret=$?
+
+kill $iperfs
+
+# Check nc can connect to 10.96.0.1:443 (aka 192.168.1.1:5201).
+if [ $ret -eq 0 ]; then
+       echo "PASS: nc can connect via NAT'd address"
+else
+       echo "FAIL: nc cannot connect via NAT'd address"
+       exit 1
+fi
+
+exit 0