From 36d4d68cd658d914ef73ac845705c4a89e7d9e2f Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Wed, 5 Apr 2017 16:26:17 +0200 Subject: [PATCH 01/91] batman-adv: Fix rx packet/bytes stats on local ARP reply The stats are generated by batadv_interface_stats and must not be stored directly in the net_device stats member variable. The batadv_priv bat_counters information is assembled when ndo_get_stats is called. The stats previously stored in net_device::stats is then overwritten. The batman-adv counters must therefore be increased when an ARP packet is answered locally via the distributed arp table. Fixes: c384ea3ec930 ("batman-adv: Distributed ARP Table - add snooping functions for ARP messages") Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/distributed-arp-table.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 013e970eff39..000ca2f113ab 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -1064,8 +1064,9 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, skb_new->protocol = eth_type_trans(skb_new, soft_iface); - soft_iface->stats.rx_packets++; - soft_iface->stats.rx_bytes += skb->len + ETH_HLEN + hdr_size; + batadv_inc_counter(bat_priv, BATADV_CNT_RX); + batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES, + skb->len + ETH_HLEN + hdr_size); netif_rx(skb_new); batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n"); From a1a745ef980a1b48299ead4ea7990e62c0516f6e Mon Sep 17 00:00:00 2001 From: Andreas Pape Date: Fri, 19 May 2017 10:01:42 +0200 Subject: [PATCH 02/91] batman-adv: fix memory leak when dropping packet from other gateway The skb must be released in the receive handler since b91a2543b4c1 ("batman-adv: Consume skb in receive handlers"). Just returning NET_RX_DROP will no longer automatically free the memory. This results in memory leaks when unicast packets from other backbones must be dropped because they share a common backbone. Fixes: 9e794b6bf4a2 ("batman-adv: drop unicast packets from other backbone gw") Signed-off-by: Andreas Pape [sven@narfation.org: adjust commit message] Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/routing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index e1ebe14ee2a6..ae9f4d37d34f 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -987,7 +987,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, batadv_dbg(BATADV_DBG_BLA, bat_priv, "recv_unicast_packet(): Dropped unicast pkt received from another backbone gw %pM.\n", orig_addr_gw); - return NET_RX_DROP; + goto free_skb; } } From c28294b941232931fbd714099798eb7aa7e865d7 Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Tue, 6 Jun 2017 15:56:54 +0200 Subject: [PATCH 03/91] net: don't call strlen on non-terminated string in dev_set_alias() KMSAN reported a use of uninitialized memory in dev_set_alias(), which was caused by calling strlcpy() (which in turn called strlen()) on the user-supplied non-terminated string. Signed-off-by: Alexander Potapenko Signed-off-by: David S. Miller --- net/core/dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index fca407b4a6ea..84e1e86a4bce 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1253,8 +1253,9 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) if (!new_ifalias) return -ENOMEM; dev->ifalias = new_ifalias; + memcpy(dev->ifalias, alias, len); + dev->ifalias[len] = 0; - strlcpy(dev->ifalias, alias, len+1); return len; } From 996652c7050c70008e4434af108be6f15f20fbd0 Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Tue, 6 Jun 2017 16:30:31 +0200 Subject: [PATCH 04/91] bnx2x: fix pf2vf bulletin DMA mapping leak When freeing VF's DMA mappings, an already NULLed pointer was checked again due to an apparent copy&paste error. Consequently, the pf2vf bulletin DMA mapping was not freed. Signed-off-by: Michal Schmidt Acked-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index bdfd53b46bc5..870ea001a720 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -3042,7 +3042,7 @@ void bnx2x_vf_pci_dealloc(struct bnx2x *bp) { BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping, sizeof(struct bnx2x_vf_mbx_msg)); - BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping, + BNX2X_PCI_FREE(bp->pf2vf_bulletin, bp->pf2vf_bulletin_mapping, sizeof(union pf_vf_bulletin)); } From e4061d572cef1f990bb7761f45d00342daa27fbd Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jun 2017 19:01:37 +0300 Subject: [PATCH 05/91] net: fix up hash documentation commit 61b905da33 ("net: Rename skb->rxhash to skb->hash") didn't update the documentation, fix this up. Cc: Tom Herbert Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- Documentation/networking/scaling.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/networking/scaling.txt b/Documentation/networking/scaling.txt index 59f4db2a0c85..f55639d71d35 100644 --- a/Documentation/networking/scaling.txt +++ b/Documentation/networking/scaling.txt @@ -122,7 +122,7 @@ associated flow of the packet. The hash is either provided by hardware or will be computed in the stack. Capable hardware can pass the hash in the receive descriptor for the packet; this would usually be the same hash used for RSS (e.g. computed Toeplitz hash). The hash is saved in -skb->rx_hash and can be used elsewhere in the stack as a hash of the +skb->hash and can be used elsewhere in the stack as a hash of the packet’s flow. Each receive hardware queue has an associated list of CPUs to which From 3a807b751c66e76bff39da4a9bd9828d7866d025 Mon Sep 17 00:00:00 2001 From: John Allen Date: Tue, 6 Jun 2017 16:55:52 -0500 Subject: [PATCH 06/91] ibmvnic: Return failure on attempted mtu change Changing the mtu is currently not supported in the ibmvnic driver. Implement .ndo_change_mtu in the driver so that attempting to use ifconfig to change the mtu will fail and present the user with an error message. Signed-off-by: John Allen Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index a93757c255f7..c0fbeb387db4 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1468,6 +1468,11 @@ static void ibmvnic_netpoll_controller(struct net_device *dev) } #endif +static int ibmvnic_change_mtu(struct net_device *netdev, int new_mtu) +{ + return -EOPNOTSUPP; +} + static const struct net_device_ops ibmvnic_netdev_ops = { .ndo_open = ibmvnic_open, .ndo_stop = ibmvnic_close, @@ -1479,6 +1484,7 @@ static const struct net_device_ops ibmvnic_netdev_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ibmvnic_netpoll_controller, #endif + .ndo_change_mtu = ibmvnic_change_mtu, }; /* ethtool functions */ From e173db36e3090d90651d97ab4bc45ace7f8cc0c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20T=C3=A9nart?= Date: Wed, 7 Jun 2017 08:17:50 +0200 Subject: [PATCH 07/91] net: mvpp2: do not bypass the mvpp22_port_mii_set function The mvpp22_port_mii_set() function was added by 2697582144dd, but the function directly returns without doing anything. This return was used when debugging and wasn't removed before sending the patch. Fix this. Fixes: 2697582144dd ("net: mvpp2: handle misc PPv2.1/PPv2.2 differences") Signed-off-by: Antoine Tenart Acked-by: Thomas Petazzoni Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index 9b875d776b29..70bca2a6fb02 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -4186,8 +4186,6 @@ static void mvpp22_port_mii_set(struct mvpp2_port *port) { u32 val; - return; - /* Only GOP port 0 has an XLG MAC */ if (port->gop_id == 0) { val = readl(port->base + MVPP22_XLG_CTRL3_REG); From 7005cade1bdbb423413f8aafcbf17a1ec614a585 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 7 Jun 2017 13:45:37 +0200 Subject: [PATCH 08/91] bpf, arm64: use separate register for state in stxr Will reported that in BPF_XADD we must use a different register in stxr instruction for the status flag due to otherwise CONSTRAINED UNPREDICTABLE behavior per architecture. Reference manual says [1]: If s == t, then one of the following behaviors must occur: * The instruction is UNDEFINED. * The instruction executes as a NOP. * The instruction performs the store to the specified address, but the value stored is UNKNOWN. Thus, use a different temporary register for the status flag to fix it. Disassembly extract from test 226/STX_XADD_DW from test_bpf.ko: [...] 0000003c: c85f7d4b ldxr x11, [x10] 00000040: 8b07016b add x11, x11, x7 00000044: c80c7d4b stxr w12, x11, [x10] 00000048: 35ffffac cbnz w12, 0x0000003c [...] [1] https://static.docs.arm.com/ddi0487/b/DDI0487B_a_armv8_arm.pdf, p.6132 Fixes: 85f68fe89832 ("bpf, arm64: implement jiting of BPF_XADD") Reported-by: Will Deacon Signed-off-by: Daniel Borkmann Acked-by: Will Deacon Signed-off-by: David S. Miller --- arch/arm64/net/bpf_jit_comp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index 71f930501ade..c870d6f01ac2 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -36,6 +36,7 @@ int bpf_jit_enable __read_mostly; #define TMP_REG_1 (MAX_BPF_JIT_REG + 0) #define TMP_REG_2 (MAX_BPF_JIT_REG + 1) #define TCALL_CNT (MAX_BPF_JIT_REG + 2) +#define TMP_REG_3 (MAX_BPF_JIT_REG + 3) /* Map BPF registers to A64 registers */ static const int bpf2a64[] = { @@ -57,6 +58,7 @@ static const int bpf2a64[] = { /* temporary registers for internal BPF JIT */ [TMP_REG_1] = A64_R(10), [TMP_REG_2] = A64_R(11), + [TMP_REG_3] = A64_R(12), /* tail_call_cnt */ [TCALL_CNT] = A64_R(26), /* temporary register for blinding constants */ @@ -319,6 +321,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) const u8 src = bpf2a64[insn->src_reg]; const u8 tmp = bpf2a64[TMP_REG_1]; const u8 tmp2 = bpf2a64[TMP_REG_2]; + const u8 tmp3 = bpf2a64[TMP_REG_3]; const s16 off = insn->off; const s32 imm = insn->imm; const int i = insn - ctx->prog->insnsi; @@ -689,10 +692,10 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) emit(A64_PRFM(tmp, PST, L1, STRM), ctx); emit(A64_LDXR(isdw, tmp2, tmp), ctx); emit(A64_ADD(isdw, tmp2, tmp2, src), ctx); - emit(A64_STXR(isdw, tmp2, tmp, tmp2), ctx); + emit(A64_STXR(isdw, tmp2, tmp, tmp3), ctx); jmp_offset = -3; check_imm19(jmp_offset); - emit(A64_CBNZ(0, tmp2, jmp_offset), ctx); + emit(A64_CBNZ(0, tmp3, jmp_offset), ctx); break; /* R0 = ntohx(*(size *)(((struct sk_buff *)R6)->data + imm)) */ From cf124db566e6b036b8bcbe8decbed740bdfac8c6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 8 May 2017 12:52:56 -0400 Subject: [PATCH 09/91] net: Fix inconsistent teardown and release of private netdev state. Network devices can allocate reasources and private memory using netdev_ops->ndo_init(). However, the release of these resources can occur in one of two different places. Either netdev_ops->ndo_uninit() or netdev->destructor(). The decision of which operation frees the resources depends upon whether it is necessary for all netdev refs to be released before it is safe to perform the freeing. netdev_ops->ndo_uninit() presumably can occur right after the NETDEV_UNREGISTER notifier completes and the unicast and multicast address lists are flushed. netdev->destructor(), on the other hand, does not run until the netdev references all go away. Further complicating the situation is that netdev->destructor() almost universally does also a free_netdev(). This creates a problem for the logic in register_netdevice(). Because all callers of register_netdevice() manage the freeing of the netdev, and invoke free_netdev(dev) if register_netdevice() fails. If netdev_ops->ndo_init() succeeds, but something else fails inside of register_netdevice(), it does call ndo_ops->ndo_uninit(). But it is not able to invoke netdev->destructor(). This is because netdev->destructor() will do a free_netdev() and then the caller of register_netdevice() will do the same. However, this means that the resources that would normally be released by netdev->destructor() will not be. Over the years drivers have added local hacks to deal with this, by invoking their destructor parts by hand when register_netdevice() fails. Many drivers do not try to deal with this, and instead we have leaks. Let's close this hole by formalizing the distinction between what private things need to be freed up by netdev->destructor() and whether the driver needs unregister_netdevice() to perform the free_netdev(). netdev->priv_destructor() performs all actions to free up the private resources that used to be freed by netdev->destructor(), except for free_netdev(). netdev->needs_free_netdev is a boolean that indicates whether free_netdev() should be done at the end of unregister_netdevice(). Now, register_netdevice() can sanely release all resources after ndo_ops->ndo_init() succeeds, by invoking both ndo_ops->ndo_uninit() and netdev->priv_destructor(). And at the end of unregister_netdevice(), we invoke netdev->priv_destructor() and optionally call free_netdev(). Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 6 +++--- drivers/net/caif/caif_hsi.c | 2 +- drivers/net/caif/caif_serial.c | 2 +- drivers/net/caif/caif_spi.c | 2 +- drivers/net/caif/caif_virtio.c | 2 +- drivers/net/can/slcan.c | 7 +++---- drivers/net/can/vcan.c | 2 +- drivers/net/can/vxcan.c | 2 +- drivers/net/dummy.c | 4 ++-- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 2 +- drivers/net/geneve.c | 2 +- drivers/net/gtp.c | 2 +- drivers/net/hamradio/6pack.c | 2 +- drivers/net/hamradio/bpqether.c | 2 +- drivers/net/ifb.c | 4 ++-- drivers/net/ipvlan/ipvlan_main.c | 2 +- drivers/net/loopback.c | 4 ++-- drivers/net/macsec.c | 4 ++-- drivers/net/macvlan.c | 2 +- drivers/net/nlmon.c | 2 +- drivers/net/slip/slip.c | 7 +++---- drivers/net/team/team.c | 4 ++-- drivers/net/tun.c | 4 ++-- drivers/net/usb/cdc-phonet.c | 2 +- drivers/net/usb/qmi_wwan.c | 2 +- drivers/net/veth.c | 4 ++-- drivers/net/vrf.c | 2 +- drivers/net/vsockmon.c | 2 +- drivers/net/vxlan.c | 2 +- drivers/net/wan/dlci.c | 2 +- drivers/net/wan/hdlc_fr.c | 2 +- drivers/net/wan/lapbether.c | 2 +- drivers/net/wireless/ath/ath6kl/main.c | 2 +- .../net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 1 - drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 3 ++- drivers/net/wireless/intersil/hostap/hostap_main.c | 2 +- drivers/net/wireless/mac80211_hwsim.c | 2 +- drivers/net/wireless/marvell/mwifiex/main.c | 2 +- drivers/staging/rtl8188eu/os_dep/mon.c | 2 +- drivers/usb/gadget/function/f_phonet.c | 2 +- include/linux/netdevice.h | 7 ++++--- net/8021q/vlan_dev.c | 4 ++-- net/batman-adv/soft-interface.c | 5 ++--- net/bluetooth/6lowpan.c | 2 +- net/bridge/br_device.c | 2 +- net/caif/chnl_net.c | 4 ++-- net/core/dev.c | 8 ++++++-- net/hsr/hsr_device.c | 4 ++-- net/ieee802154/6lowpan/core.c | 2 +- net/ipv4/ip_tunnel.c | 4 ++-- net/ipv4/ipmr.c | 2 +- net/ipv6/ip6_gre.c | 9 +++++---- net/ipv6/ip6_tunnel.c | 8 ++++---- net/ipv6/ip6_vti.c | 8 ++++---- net/ipv6/ip6mr.c | 2 +- net/ipv6/sit.c | 6 +++--- net/irda/irlan/irlan_eth.c | 2 +- net/l2tp/l2tp_eth.c | 2 +- net/mac80211/iface.c | 6 +++--- net/mac802154/iface.c | 7 +++---- net/openvswitch/vport-internal_dev.c | 4 ++-- net/phonet/pep-gprs.c | 2 +- 62 files changed, 105 insertions(+), 103 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2359478b977f..8ab6bdbe1682 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4192,7 +4192,6 @@ static void bond_destructor(struct net_device *bond_dev) struct bonding *bond = netdev_priv(bond_dev); if (bond->wq) destroy_workqueue(bond->wq); - free_netdev(bond_dev); } void bond_setup(struct net_device *bond_dev) @@ -4212,7 +4211,8 @@ void bond_setup(struct net_device *bond_dev) bond_dev->netdev_ops = &bond_netdev_ops; bond_dev->ethtool_ops = &bond_ethtool_ops; - bond_dev->destructor = bond_destructor; + bond_dev->needs_free_netdev = true; + bond_dev->priv_destructor = bond_destructor; SET_NETDEV_DEVTYPE(bond_dev, &bond_type); @@ -4736,7 +4736,7 @@ int bond_create(struct net *net, const char *name) rtnl_unlock(); if (res < 0) - bond_destructor(bond_dev); + free_netdev(bond_dev); return res; } diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c index ddabce759456..71a7c3b44fdd 100644 --- a/drivers/net/caif/caif_hsi.c +++ b/drivers/net/caif/caif_hsi.c @@ -1121,7 +1121,7 @@ static void cfhsi_setup(struct net_device *dev) dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->mtu = CFHSI_MAX_CAIF_FRAME_SZ; dev->priv_flags |= IFF_NO_QUEUE; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->netdev_ops = &cfhsi_netdevops; for (i = 0; i < CFHSI_PRIO_LAST; ++i) skb_queue_head_init(&cfhsi->qhead[i]); diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index c2dea4916e5d..76e1d3545105 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -428,7 +428,7 @@ static void caifdev_setup(struct net_device *dev) dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->mtu = CAIF_MAX_MTU; dev->priv_flags |= IFF_NO_QUEUE; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; skb_queue_head_init(&serdev->head); serdev->common.link_select = CAIF_LINK_LOW_LATENCY; serdev->common.use_frag = true; diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c index 3a529fbe539f..fc21afe852b9 100644 --- a/drivers/net/caif/caif_spi.c +++ b/drivers/net/caif/caif_spi.c @@ -712,7 +712,7 @@ static void cfspi_setup(struct net_device *dev) dev->flags = IFF_NOARP | IFF_POINTOPOINT; dev->priv_flags |= IFF_NO_QUEUE; dev->mtu = SPI_MAX_PAYLOAD_SIZE; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; skb_queue_head_init(&cfspi->qhead); skb_queue_head_init(&cfspi->chead); cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW; diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c index 6122768c8644..1794ea0420b7 100644 --- a/drivers/net/caif/caif_virtio.c +++ b/drivers/net/caif/caif_virtio.c @@ -617,7 +617,7 @@ static void cfv_netdev_setup(struct net_device *netdev) netdev->tx_queue_len = 100; netdev->flags = IFF_POINTOPOINT | IFF_NOARP; netdev->mtu = CFV_DEF_MTU_SIZE; - netdev->destructor = free_netdev; + netdev->needs_free_netdev = true; } /* Create debugfs counters for the device */ diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index eb7173713bbc..6a6e896e52fa 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -417,7 +417,7 @@ static int slc_open(struct net_device *dev) static void slc_free_netdev(struct net_device *dev) { int i = dev->base_addr; - free_netdev(dev); + slcan_devs[i] = NULL; } @@ -436,7 +436,8 @@ static const struct net_device_ops slc_netdev_ops = { static void slc_setup(struct net_device *dev) { dev->netdev_ops = &slc_netdev_ops; - dev->destructor = slc_free_netdev; + dev->needs_free_netdev = true; + dev->priv_destructor = slc_free_netdev; dev->hard_header_len = 0; dev->addr_len = 0; @@ -761,8 +762,6 @@ static void __exit slcan_exit(void) if (sl->tty) { printk(KERN_ERR "%s: tty discipline still running\n", dev->name); - /* Intentionally leak the control block. */ - dev->destructor = NULL; } unregister_netdev(dev); diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index facca33d53e9..0eda1b308583 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -163,7 +163,7 @@ static void vcan_setup(struct net_device *dev) dev->flags |= IFF_ECHO; dev->netdev_ops = &vcan_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; } static struct rtnl_link_ops vcan_link_ops __read_mostly = { diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index 7fbb24795681..30cf2368becf 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -156,7 +156,7 @@ static void vxcan_setup(struct net_device *dev) dev->tx_queue_len = 0; dev->flags = (IFF_NOARP|IFF_ECHO); dev->netdev_ops = &vxcan_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; } /* forward declaration for rtnl_create_link() */ diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 149244aac20a..9905b52fe293 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -328,7 +328,6 @@ static void dummy_free_netdev(struct net_device *dev) struct dummy_priv *priv = netdev_priv(dev); kfree(priv->vfinfo); - free_netdev(dev); } static void dummy_setup(struct net_device *dev) @@ -338,7 +337,8 @@ static void dummy_setup(struct net_device *dev) /* Initialize the device structure. */ dev->netdev_ops = &dummy_netdev_ops; dev->ethtool_ops = &dummy_ethtool_ops; - dev->destructor = dummy_free_netdev; + dev->needs_free_netdev = true; + dev->priv_destructor = dummy_free_netdev; /* Fill in device structure with ethernet-generic values. */ dev->flags |= IFF_NOARP; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 77ed2f628f9c..ea1bfcf1870a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -4525,7 +4525,7 @@ static void dummy_setup(struct net_device *dev) /* Initialize the device structure. */ dev->netdev_ops = &cxgb4_mgmt_netdev_ops; dev->ethtool_ops = &cxgb4_mgmt_ethtool_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; } static int config_mgmt_dev(struct pci_dev *pdev) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 6ebb0f559a42..199459bd6961 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1007,7 +1007,7 @@ static void geneve_setup(struct net_device *dev) dev->netdev_ops = &geneve_netdev_ops; dev->ethtool_ops = &geneve_ethtool_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; SET_NETDEV_DEVTYPE(dev, &geneve_type); diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 7b652bb7ebe4..ca110cd2a4e4 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -611,7 +611,7 @@ static const struct net_device_ops gtp_netdev_ops = { static void gtp_link_setup(struct net_device *dev) { dev->netdev_ops = >p_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->hard_header_len = 0; dev->addr_len = 0; diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 922bf440e9f1..021a8ec411ab 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -311,7 +311,7 @@ static void sp_setup(struct net_device *dev) { /* Finish setting up the DEVICE info. */ dev->netdev_ops = &sp_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->mtu = SIXP_MTU; dev->hard_header_len = AX25_MAX_HEADER_LEN; dev->header_ops = &ax25_header_ops; diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index f62e7f325cf9..78a6414c5fd9 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -476,7 +476,7 @@ static const struct net_device_ops bpq_netdev_ops = { static void bpq_setup(struct net_device *dev) { dev->netdev_ops = &bpq_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 312fce7302d3..144ea5ae8ab4 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -207,7 +207,6 @@ static void ifb_dev_free(struct net_device *dev) __skb_queue_purge(&txp->tq); } kfree(dp->tx_private); - free_netdev(dev); } static void ifb_setup(struct net_device *dev) @@ -230,7 +229,8 @@ static void ifb_setup(struct net_device *dev) dev->priv_flags &= ~IFF_TX_SKB_SHARING; netif_keep_dst(dev); eth_hw_addr_random(dev); - dev->destructor = ifb_dev_free; + dev->needs_free_netdev = true; + dev->priv_destructor = ifb_dev_free; } static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev) diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 618ed88fad0f..7c7680c8f0e3 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -632,7 +632,7 @@ void ipvlan_link_setup(struct net_device *dev) dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); dev->priv_flags |= IFF_UNICAST_FLT | IFF_NO_QUEUE; dev->netdev_ops = &ipvlan_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->header_ops = &ipvlan_header_ops; dev->ethtool_ops = &ipvlan_ethtool_ops; } diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 224f65cb576b..30612497643c 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -159,7 +159,6 @@ static void loopback_dev_free(struct net_device *dev) { dev_net(dev)->loopback_dev = NULL; free_percpu(dev->lstats); - free_netdev(dev); } static const struct net_device_ops loopback_ops = { @@ -196,7 +195,8 @@ static void loopback_setup(struct net_device *dev) dev->ethtool_ops = &loopback_ethtool_ops; dev->header_ops = ð_header_ops; dev->netdev_ops = &loopback_ops; - dev->destructor = loopback_dev_free; + dev->needs_free_netdev = true; + dev->priv_destructor = loopback_dev_free; } /* Setup and register the loopback device. */ diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index cdc347be68f2..79411675f0e6 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -2996,7 +2996,6 @@ static void macsec_free_netdev(struct net_device *dev) free_percpu(macsec->secy.tx_sc.stats); dev_put(real_dev); - free_netdev(dev); } static void macsec_setup(struct net_device *dev) @@ -3006,7 +3005,8 @@ static void macsec_setup(struct net_device *dev) dev->max_mtu = ETH_MAX_MTU; dev->priv_flags |= IFF_NO_QUEUE; dev->netdev_ops = &macsec_netdev_ops; - dev->destructor = macsec_free_netdev; + dev->needs_free_netdev = true; + dev->priv_destructor = macsec_free_netdev; SET_NETDEV_DEVTYPE(dev, &macsec_type); eth_zero_addr(dev->broadcast); diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 346ad2ff3998..67bf7ebae5c6 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -1092,7 +1092,7 @@ void macvlan_common_setup(struct net_device *dev) netif_keep_dst(dev); dev->priv_flags |= IFF_UNICAST_FLT; dev->netdev_ops = &macvlan_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->header_ops = &macvlan_hard_header_ops; dev->ethtool_ops = &macvlan_ethtool_ops; } diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c index b91603835d26..c4b3362da4a2 100644 --- a/drivers/net/nlmon.c +++ b/drivers/net/nlmon.c @@ -113,7 +113,7 @@ static void nlmon_setup(struct net_device *dev) dev->netdev_ops = &nlmon_ops; dev->ethtool_ops = &nlmon_ethtool_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | NETIF_F_LLTX; diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index 1da31dc47f86..74b907206aa7 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -629,7 +629,7 @@ static void sl_uninit(struct net_device *dev) static void sl_free_netdev(struct net_device *dev) { int i = dev->base_addr; - free_netdev(dev); + slip_devs[i] = NULL; } @@ -651,7 +651,8 @@ static const struct net_device_ops sl_netdev_ops = { static void sl_setup(struct net_device *dev) { dev->netdev_ops = &sl_netdev_ops; - dev->destructor = sl_free_netdev; + dev->needs_free_netdev = true; + dev->priv_destructor = sl_free_netdev; dev->hard_header_len = 0; dev->addr_len = 0; @@ -1369,8 +1370,6 @@ static void __exit slip_exit(void) if (sl->tty) { printk(KERN_ERR "%s: tty discipline still running\n", dev->name); - /* Intentionally leak the control block. */ - dev->destructor = NULL; } unregister_netdev(dev); diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 6c5d5ef46f75..fba8c136aa7c 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1643,7 +1643,6 @@ static void team_destructor(struct net_device *dev) struct team *team = netdev_priv(dev); free_percpu(team->pcpu_stats); - free_netdev(dev); } static int team_open(struct net_device *dev) @@ -2079,7 +2078,8 @@ static void team_setup(struct net_device *dev) dev->netdev_ops = &team_netdev_ops; dev->ethtool_ops = &team_ethtool_ops; - dev->destructor = team_destructor; + dev->needs_free_netdev = true; + dev->priv_destructor = team_destructor; dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); dev->priv_flags |= IFF_NO_QUEUE; dev->priv_flags |= IFF_TEAM; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index bbd707b9ef7a..9ee7d4275640 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1560,7 +1560,6 @@ static void tun_free_netdev(struct net_device *dev) free_percpu(tun->pcpu_stats); tun_flow_uninit(tun); security_tun_dev_free_security(tun->security); - free_netdev(dev); } static void tun_setup(struct net_device *dev) @@ -1571,7 +1570,8 @@ static void tun_setup(struct net_device *dev) tun->group = INVALID_GID; dev->ethtool_ops = &tun_ethtool_ops; - dev->destructor = tun_free_netdev; + dev->needs_free_netdev = true; + dev->priv_destructor = tun_free_netdev; /* We prefer our own queue length */ dev->tx_queue_len = TUN_READQ_SIZE; } diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index eb52de8205f0..c7a350bbaaa7 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -298,7 +298,7 @@ static void usbpn_setup(struct net_device *dev) dev->addr_len = 1; dev->tx_queue_len = 3; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; } /* diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 8f923a147fa9..949671ce4039 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -123,7 +123,7 @@ static void qmimux_setup(struct net_device *dev) dev->addr_len = 0; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; dev->netdev_ops = &qmimux_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; } static struct net_device *qmimux_find_dev(struct usbnet *dev, u8 mux_id) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 38f0f03a29c8..0156fe8cac17 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -222,7 +222,6 @@ static int veth_dev_init(struct net_device *dev) static void veth_dev_free(struct net_device *dev) { free_percpu(dev->vstats); - free_netdev(dev); } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -317,7 +316,8 @@ static void veth_setup(struct net_device *dev) NETIF_F_HW_VLAN_STAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX); - dev->destructor = veth_dev_free; + dev->needs_free_netdev = true; + dev->priv_destructor = veth_dev_free; dev->max_mtu = ETH_MAX_MTU; dev->hw_features = VETH_FEATURES; diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index db882493875c..d38f11d833fe 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -1348,7 +1348,7 @@ static void vrf_setup(struct net_device *dev) dev->netdev_ops = &vrf_netdev_ops; dev->l3mdev_ops = &vrf_l3mdev_ops; dev->ethtool_ops = &vrf_ethtool_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; /* Fill in device structure with ethernet-generic values. */ eth_hw_addr_random(dev); diff --git a/drivers/net/vsockmon.c b/drivers/net/vsockmon.c index 7f0136f2dd9d..c28bdce14fd5 100644 --- a/drivers/net/vsockmon.c +++ b/drivers/net/vsockmon.c @@ -135,7 +135,7 @@ static void vsockmon_setup(struct net_device *dev) dev->netdev_ops = &vsockmon_ops; dev->ethtool_ops = &vsockmon_ethtool_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | NETIF_F_LLTX; diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index a6b5052c1d36..5fa798a5c9a6 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2611,7 +2611,7 @@ static void vxlan_setup(struct net_device *dev) eth_hw_addr_random(dev); ether_setup(dev); - dev->destructor = free_netdev; + dev->needs_free_netdev = true; SET_NETDEV_DEVTYPE(dev, &vxlan_type); dev->features |= NETIF_F_LLTX; diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index 65ee2a6f248c..a0d76f70c428 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -475,7 +475,7 @@ static void dlci_setup(struct net_device *dev) dev->flags = 0; dev->header_ops = &dlci_header_ops; dev->netdev_ops = &dlci_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dlp->receive = dlci_receive; diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index eb915281197e..78596e42a3f3 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -1106,7 +1106,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) return -EIO; } - dev->destructor = free_netdev; + dev->needs_free_netdev = true; *get_dev_p(pvc, type) = dev; if (!used) { state(hdlc)->dce_changed = 1; diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index 9df9ed62beff..63f749078a1f 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -306,7 +306,7 @@ static const struct net_device_ops lapbeth_netdev_ops = { static void lapbeth_setup(struct net_device *dev) { dev->netdev_ops = &lapbeth_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->type = ARPHRD_X25; dev->hard_header_len = 3; dev->mtu = 1000; diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 91ee542de3d7..b90c77ef792e 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -1287,7 +1287,7 @@ void init_netdev(struct net_device *dev) struct ath6kl *ar = ath6kl_priv(dev); dev->netdev_ops = &ath6kl_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; dev->needed_headroom = ETH_HLEN; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index cd1d6730eab7..617199c0e5a0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -5225,7 +5225,6 @@ void brcmf_cfg80211_free_netdev(struct net_device *ndev) if (vif) brcmf_free_vif(vif); - free_netdev(ndev); } static bool brcmf_is_linkup(const struct brcmf_event_msg *e) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index a3d82368f1a9..511d190c6cca 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -624,7 +624,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx, if (!ndev) return ERR_PTR(-ENOMEM); - ndev->destructor = brcmf_cfg80211_free_netdev; + ndev->needs_free_netdev = true; + ndev->priv_destructor = brcmf_cfg80211_free_netdev; ifp = netdev_priv(ndev); ifp->ndev = ndev; /* store mapping ifidx to bsscfgidx */ diff --git a/drivers/net/wireless/intersil/hostap/hostap_main.c b/drivers/net/wireless/intersil/hostap/hostap_main.c index 544fc09dcb62..1372b20f931e 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_main.c +++ b/drivers/net/wireless/intersil/hostap/hostap_main.c @@ -73,7 +73,7 @@ struct net_device * hostap_add_interface(struct local_info *local, dev->mem_end = mdev->mem_end; hostap_setup_dev(dev, local, type); - dev->destructor = free_netdev; + dev->needs_free_netdev = true; sprintf(dev->name, "%s%s", prefix, name); if (!rtnl_locked) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 002b25cff5b6..c854a557998b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2861,7 +2861,7 @@ static const struct net_device_ops hwsim_netdev_ops = { static void hwsim_mon_setup(struct net_device *dev) { dev->netdev_ops = &hwsim_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; ether_setup(dev); dev->priv_flags |= IFF_NO_QUEUE; dev->type = ARPHRD_IEEE80211_RADIOTAP; diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index dd87b9ff64c3..39b6b5e3f6e0 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -1280,7 +1280,7 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev) { dev->netdev_ops = &mwifiex_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; /* Initialize private structure */ priv->current_key_index = 0; priv->media_connected = false; diff --git a/drivers/staging/rtl8188eu/os_dep/mon.c b/drivers/staging/rtl8188eu/os_dep/mon.c index cfe37eb026d6..859d0d6051cd 100644 --- a/drivers/staging/rtl8188eu/os_dep/mon.c +++ b/drivers/staging/rtl8188eu/os_dep/mon.c @@ -152,7 +152,7 @@ static const struct net_device_ops mon_netdev_ops = { static void mon_setup(struct net_device *dev) { dev->netdev_ops = &mon_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; ether_setup(dev); dev->priv_flags |= IFF_NO_QUEUE; dev->type = ARPHRD_IEEE80211; diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c index b4058f0000e4..6a1ce6a55158 100644 --- a/drivers/usb/gadget/function/f_phonet.c +++ b/drivers/usb/gadget/function/f_phonet.c @@ -281,7 +281,7 @@ static void pn_net_setup(struct net_device *dev) dev->tx_queue_len = 1; dev->netdev_ops = &pn_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->header_ops = &phonet_header_ops; } diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 3f39d27decf4..ab7ca3fdc495 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1596,8 +1596,8 @@ enum netdev_priv_flags { * @rtnl_link_state: This enum represents the phases of creating * a new link * - * @destructor: Called from unregister, - * can be used to call free_netdev + * @needs_free_netdev: Should unregister perform free_netdev? + * @priv_destructor: Called from unregister * @npinfo: XXX: need comments on this one * @nd_net: Network namespace this network device is inside * @@ -1858,7 +1858,8 @@ struct net_device { RTNL_LINK_INITIALIZING, } rtnl_link_state:16; - void (*destructor)(struct net_device *dev); + bool needs_free_netdev; + void (*priv_destructor)(struct net_device *dev); #ifdef CONFIG_NETPOLL struct netpoll_info __rcu *npinfo; diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 953b6728bd00..abc5f400fc71 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -813,7 +813,6 @@ static void vlan_dev_free(struct net_device *dev) free_percpu(vlan->vlan_pcpu_stats); vlan->vlan_pcpu_stats = NULL; - free_netdev(dev); } void vlan_setup(struct net_device *dev) @@ -826,7 +825,8 @@ void vlan_setup(struct net_device *dev) netif_keep_dst(dev); dev->netdev_ops = &vlan_netdev_ops; - dev->destructor = vlan_dev_free; + dev->needs_free_netdev = true; + dev->priv_destructor = vlan_dev_free; dev->ethtool_ops = &vlan_ethtool_ops; dev->min_mtu = 0; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index b25789abf7b9..10f7edfb176e 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -1034,8 +1034,6 @@ static void batadv_softif_free(struct net_device *dev) * netdev and its private data (bat_priv) */ rcu_barrier(); - - free_netdev(dev); } /** @@ -1047,7 +1045,8 @@ static void batadv_softif_init_early(struct net_device *dev) ether_setup(dev); dev->netdev_ops = &batadv_netdev_ops; - dev->destructor = batadv_softif_free; + dev->needs_free_netdev = true; + dev->priv_destructor = batadv_softif_free; dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_NETNS_LOCAL; dev->priv_flags |= IFF_NO_QUEUE; diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 608959989f8e..ab3b654b05cc 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -598,7 +598,7 @@ static void netdev_setup(struct net_device *dev) dev->netdev_ops = &netdev_ops; dev->header_ops = &header_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; } static struct device_type bt_type = { diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 430b53e7d941..f0f3447e8aa4 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -379,7 +379,7 @@ void br_dev_setup(struct net_device *dev) ether_setup(dev); dev->netdev_ops = &br_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->ethtool_ops = &br_ethtool_ops; SET_NETDEV_DEVTYPE(dev, &br_type); dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE; diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 1816fc9f1ee7..fe3c53efb949 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -392,14 +392,14 @@ static void chnl_net_destructor(struct net_device *dev) { struct chnl_net *priv = netdev_priv(dev); caif_free_client(&priv->chnl); - free_netdev(dev); } static void ipcaif_net_setup(struct net_device *dev) { struct chnl_net *priv; dev->netdev_ops = &netdev_ops; - dev->destructor = chnl_net_destructor; + dev->needs_free_netdev = true; + dev->priv_destructor = chnl_net_destructor; dev->flags |= IFF_NOARP; dev->flags |= IFF_POINTOPOINT; dev->mtu = GPRS_PDP_MTU; diff --git a/net/core/dev.c b/net/core/dev.c index 84e1e86a4bce..4c15466305c3 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -7502,6 +7502,8 @@ int register_netdevice(struct net_device *dev) err_uninit: if (dev->netdev_ops->ndo_uninit) dev->netdev_ops->ndo_uninit(dev); + if (dev->priv_destructor) + dev->priv_destructor(dev); goto out; } EXPORT_SYMBOL(register_netdevice); @@ -7709,8 +7711,10 @@ void netdev_run_todo(void) WARN_ON(rcu_access_pointer(dev->ip6_ptr)); WARN_ON(dev->dn_ptr); - if (dev->destructor) - dev->destructor(dev); + if (dev->priv_destructor) + dev->priv_destructor(dev); + if (dev->needs_free_netdev) + free_netdev(dev); /* Report a network device has been unregistered */ rtnl_lock(); diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index c73160fb11e7..0a0a392dc2bd 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c @@ -378,7 +378,6 @@ static void hsr_dev_destroy(struct net_device *hsr_dev) del_timer_sync(&hsr->announce_timer); synchronize_rcu(); - free_netdev(hsr_dev); } static const struct net_device_ops hsr_device_ops = { @@ -404,7 +403,8 @@ void hsr_dev_setup(struct net_device *dev) SET_NETDEV_DEVTYPE(dev, &hsr_type); dev->priv_flags |= IFF_NO_QUEUE; - dev->destructor = hsr_dev_destroy; + dev->needs_free_netdev = true; + dev->priv_destructor = hsr_dev_destroy; dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c index d7efbf0dad20..0a866f332290 100644 --- a/net/ieee802154/6lowpan/core.c +++ b/net/ieee802154/6lowpan/core.c @@ -107,7 +107,7 @@ static void lowpan_setup(struct net_device *ldev) ldev->netdev_ops = &lowpan_netdev_ops; ldev->header_ops = &lowpan_header_ops; - ldev->destructor = free_netdev; + ldev->needs_free_netdev = true; ldev->features |= NETIF_F_NETNS_LOCAL; } diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index b878ecbc0608..b436d0775631 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -967,7 +967,6 @@ static void ip_tunnel_dev_free(struct net_device *dev) gro_cells_destroy(&tunnel->gro_cells); dst_cache_destroy(&tunnel->dst_cache); free_percpu(dev->tstats); - free_netdev(dev); } void ip_tunnel_dellink(struct net_device *dev, struct list_head *head) @@ -1155,7 +1154,8 @@ int ip_tunnel_init(struct net_device *dev) struct iphdr *iph = &tunnel->parms.iph; int err; - dev->destructor = ip_tunnel_dev_free; + dev->needs_free_netdev = true; + dev->priv_destructor = ip_tunnel_dev_free; dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!dev->tstats) return -ENOMEM; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 551de4d023a8..b4f9622ee9f5 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -501,7 +501,7 @@ static void reg_vif_setup(struct net_device *dev) dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 8; dev->flags = IFF_NOARP; dev->netdev_ops = ®_vif_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->features |= NETIF_F_NETNS_LOCAL; } diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 0c5b4caa1949..64eea3962733 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -991,13 +991,13 @@ static void ip6gre_dev_free(struct net_device *dev) dst_cache_destroy(&t->dst_cache); free_percpu(dev->tstats); - free_netdev(dev); } static void ip6gre_tunnel_setup(struct net_device *dev) { dev->netdev_ops = &ip6gre_netdev_ops; - dev->destructor = ip6gre_dev_free; + dev->needs_free_netdev = true; + dev->priv_destructor = ip6gre_dev_free; dev->type = ARPHRD_IP6GRE; @@ -1148,7 +1148,7 @@ static int __net_init ip6gre_init_net(struct net *net) return 0; err_reg_dev: - ip6gre_dev_free(ign->fb_tunnel_dev); + free_netdev(ign->fb_tunnel_dev); err_alloc_dev: return err; } @@ -1300,7 +1300,8 @@ static void ip6gre_tap_setup(struct net_device *dev) ether_setup(dev); dev->netdev_ops = &ip6gre_tap_netdev_ops; - dev->destructor = ip6gre_dev_free; + dev->needs_free_netdev = true; + dev->priv_destructor = ip6gre_dev_free; dev->features |= NETIF_F_NETNS_LOCAL; dev->priv_flags &= ~IFF_TX_SKB_SHARING; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 9b37f9747fc6..c3581973f5d7 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -254,7 +254,6 @@ static void ip6_dev_free(struct net_device *dev) gro_cells_destroy(&t->gro_cells); dst_cache_destroy(&t->dst_cache); free_percpu(dev->tstats); - free_netdev(dev); } static int ip6_tnl_create2(struct net_device *dev) @@ -322,7 +321,7 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p) return t; failed_free: - ip6_dev_free(dev); + free_netdev(dev); failed: return ERR_PTR(err); } @@ -1777,7 +1776,8 @@ static const struct net_device_ops ip6_tnl_netdev_ops = { static void ip6_tnl_dev_setup(struct net_device *dev) { dev->netdev_ops = &ip6_tnl_netdev_ops; - dev->destructor = ip6_dev_free; + dev->needs_free_netdev = true; + dev->priv_destructor = ip6_dev_free; dev->type = ARPHRD_TUNNEL6; dev->flags |= IFF_NOARP; @@ -2224,7 +2224,7 @@ static int __net_init ip6_tnl_init_net(struct net *net) return 0; err_register: - ip6_dev_free(ip6n->fb_tnl_dev); + free_netdev(ip6n->fb_tnl_dev); err_alloc_dev: return err; } diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index d67ef56454b2..837ea1eefe7f 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -180,7 +180,6 @@ vti6_tnl_unlink(struct vti6_net *ip6n, struct ip6_tnl *t) static void vti6_dev_free(struct net_device *dev) { free_percpu(dev->tstats); - free_netdev(dev); } static int vti6_tnl_create2(struct net_device *dev) @@ -235,7 +234,7 @@ static struct ip6_tnl *vti6_tnl_create(struct net *net, struct __ip6_tnl_parm *p return t; failed_free: - vti6_dev_free(dev); + free_netdev(dev); failed: return NULL; } @@ -842,7 +841,8 @@ static const struct net_device_ops vti6_netdev_ops = { static void vti6_dev_setup(struct net_device *dev) { dev->netdev_ops = &vti6_netdev_ops; - dev->destructor = vti6_dev_free; + dev->needs_free_netdev = true; + dev->priv_destructor = vti6_dev_free; dev->type = ARPHRD_TUNNEL6; dev->hard_header_len = LL_MAX_HEADER + sizeof(struct ipv6hdr); @@ -1100,7 +1100,7 @@ static int __net_init vti6_init_net(struct net *net) return 0; err_register: - vti6_dev_free(ip6n->fb_tnl_dev); + free_netdev(ip6n->fb_tnl_dev); err_alloc_dev: return err; } diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 374997d26488..2ecb39b943b5 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -733,7 +733,7 @@ static void reg_vif_setup(struct net_device *dev) dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8; dev->flags = IFF_NOARP; dev->netdev_ops = ®_vif_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->features |= NETIF_F_NETNS_LOCAL; } diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 61e5902f0687..2378503577b0 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -265,7 +265,7 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, return nt; failed_free: - ipip6_dev_free(dev); + free_netdev(dev); failed: return NULL; } @@ -1336,7 +1336,6 @@ static void ipip6_dev_free(struct net_device *dev) dst_cache_destroy(&tunnel->dst_cache); free_percpu(dev->tstats); - free_netdev(dev); } #define SIT_FEATURES (NETIF_F_SG | \ @@ -1351,7 +1350,8 @@ static void ipip6_tunnel_setup(struct net_device *dev) int t_hlen = tunnel->hlen + sizeof(struct iphdr); dev->netdev_ops = &ipip6_netdev_ops; - dev->destructor = ipip6_dev_free; + dev->needs_free_netdev = true; + dev->priv_destructor = ipip6_dev_free; dev->type = ARPHRD_SIT; dev->hard_header_len = LL_MAX_HEADER + t_hlen; diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index 74d09f91709e..3be852808a9d 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c @@ -65,7 +65,7 @@ static void irlan_eth_setup(struct net_device *dev) ether_setup(dev); dev->netdev_ops = &irlan_eth_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->min_mtu = 0; dev->max_mtu = ETH_MAX_MTU; diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 8b21af7321b9..f7c54ece3733 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -141,7 +141,7 @@ static void l2tp_eth_dev_setup(struct net_device *dev) dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->features |= NETIF_F_LLTX; dev->netdev_ops = &l2tp_eth_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; } static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 8fae1a72e6a7..915d7e1b4545 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1213,7 +1213,6 @@ static const struct net_device_ops ieee80211_monitorif_ops = { static void ieee80211_if_free(struct net_device *dev) { free_percpu(dev->tstats); - free_netdev(dev); } static void ieee80211_if_setup(struct net_device *dev) @@ -1221,7 +1220,8 @@ static void ieee80211_if_setup(struct net_device *dev) ether_setup(dev); dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->netdev_ops = &ieee80211_dataif_ops; - dev->destructor = ieee80211_if_free; + dev->needs_free_netdev = true; + dev->priv_destructor = ieee80211_if_free; } static void ieee80211_if_setup_no_queue(struct net_device *dev) @@ -1905,7 +1905,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, ret = register_netdevice(ndev); if (ret) { - ieee80211_if_free(ndev); + free_netdev(ndev); return ret; } } diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 06019dba4b10..bd88a9b80773 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -526,8 +526,6 @@ static void mac802154_wpan_free(struct net_device *dev) struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); mac802154_llsec_destroy(&sdata->sec); - - free_netdev(dev); } static void ieee802154_if_setup(struct net_device *dev) @@ -593,7 +591,8 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, sdata->dev->dev_addr); sdata->dev->header_ops = &mac802154_header_ops; - sdata->dev->destructor = mac802154_wpan_free; + sdata->dev->needs_free_netdev = true; + sdata->dev->priv_destructor = mac802154_wpan_free; sdata->dev->netdev_ops = &mac802154_wpan_ops; sdata->dev->ml_priv = &mac802154_mlme_wpan; wpan_dev->promiscuous_mode = false; @@ -608,7 +607,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, break; case NL802154_IFTYPE_MONITOR: - sdata->dev->destructor = free_netdev; + sdata->dev->needs_free_netdev = true; sdata->dev->netdev_ops = &mac802154_monitor_ops; wpan_dev->promiscuous_mode = true; break; diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c index 89193a634da4..04a3128adcf0 100644 --- a/net/openvswitch/vport-internal_dev.c +++ b/net/openvswitch/vport-internal_dev.c @@ -94,7 +94,6 @@ static void internal_dev_destructor(struct net_device *dev) struct vport *vport = ovs_internal_dev_get_vport(dev); ovs_vport_free(vport); - free_netdev(dev); } static void @@ -156,7 +155,8 @@ static void do_setup(struct net_device *netdev) netdev->priv_flags &= ~IFF_TX_SKB_SHARING; netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_OPENVSWITCH | IFF_PHONY_HEADROOM | IFF_NO_QUEUE; - netdev->destructor = internal_dev_destructor; + netdev->needs_free_netdev = true; + netdev->priv_destructor = internal_dev_destructor; netdev->ethtool_ops = &internal_dev_ethtool_ops; netdev->rtnl_link_ops = &internal_dev_link_ops; diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c index 21c28b51be94..2c9337946e30 100644 --- a/net/phonet/pep-gprs.c +++ b/net/phonet/pep-gprs.c @@ -236,7 +236,7 @@ static void gprs_setup(struct net_device *dev) dev->tx_queue_len = 10; dev->netdev_ops = &gprs_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; } /* From cd1997f6c11483da819a7719aa013093b8003743 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 8 Jun 2017 19:06:29 +1000 Subject: [PATCH 10/91] net: s390: fix up for "Fix inconsistent teardown and release of private netdev state" Signed-off-by: Stephen Rothwell Signed-off-by: David S. Miller --- drivers/s390/net/netiucv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index dba94b486f05..fa732bd86729 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1954,7 +1954,6 @@ static void netiucv_free_netdevice(struct net_device *dev) privptr->conn = NULL; privptr->fsm = NULL; /* privptr gets freed by free_netdev() */ } - free_netdev(dev); } /** @@ -1972,7 +1971,8 @@ static void netiucv_setup_netdevice(struct net_device *dev) dev->mtu = NETIUCV_MTU_DEFAULT; dev->min_mtu = 576; dev->max_mtu = NETIUCV_MTU_MAX; - dev->destructor = netiucv_free_netdevice; + dev->needs_free_netdev = true; + dev->priv_destructor = netiucv_free_netdevice; dev->hard_header_len = NETIUCV_HDRLEN; dev->addr_len = 0; dev->type = ARPHRD_SLIP; From ed66e50d9587fc0bb032e276a2563c0068a5b63a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 8 Jun 2017 10:16:05 -0400 Subject: [PATCH 11/91] hsi: Fix build regression due to netdev destructor fix. > ../drivers/hsi/clients/ssi_protocol.c:1069:5: error: 'struct net_device' has no member named 'destructor' Reported-by: Mark Brown Reported-by: Stephen Rothwell Signed-off-by: David S. Miller --- drivers/hsi/clients/ssi_protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index 26b05106f0d3..93d28c0ec8bf 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c @@ -1066,7 +1066,7 @@ static void ssip_pn_setup(struct net_device *dev) dev->addr_len = 1; dev->tx_queue_len = SSIP_TXQUEUE_LEN; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; dev->header_ops = &phonet_header_ops; } From 85eac2ba35a2dbfbdd5767c7447a4af07444a5b4 Mon Sep 17 00:00:00 2001 From: Mateusz Jurczyk Date: Wed, 7 Jun 2017 15:14:29 +0200 Subject: [PATCH 12/91] decnet: dn_rtmsg: Improve input length sanitization in dnrmg_receive_user_skb Verify that the length of the socket buffer is sufficient to cover the entire nlh->nlmsg_len field before accessing that field for further input sanitization. If the client only supplies 1-3 bytes of data in sk_buff, then nlh->nlmsg_len remains partially uninitialized and contains leftover memory from the corresponding kernel allocation. Operating on such data may result in indeterminate evaluation of the nlmsg_len < sizeof(*nlh) expression. The bug was discovered by a runtime instrumentation designed to detect use of uninitialized memory in the kernel. The patch prevents this and other similar tools (e.g. KMSAN) from flagging this behavior in the future. Signed-off-by: Mateusz Jurczyk Signed-off-by: David S. Miller --- net/decnet/netfilter/dn_rtmsg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c index 1ed81ac6dd1a..26e020e9d415 100644 --- a/net/decnet/netfilter/dn_rtmsg.c +++ b/net/decnet/netfilter/dn_rtmsg.c @@ -102,7 +102,9 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb) { struct nlmsghdr *nlh = nlmsg_hdr(skb); - if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) + if (skb->len < sizeof(nlh->nlmsg_len) || + nlh->nlmsg_len < sizeof(*nlh) || + skb->len < nlh->nlmsg_len) return; if (!netlink_capable(skb, CAP_NET_ADMIN)) From 19d90ece81da802207a9b91ce95a29fbdc40626e Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 7 Jun 2017 15:51:15 +0200 Subject: [PATCH 13/91] net: emac: fix reset timeout with AR8035 phy This patch fixes a problem where the AR8035 PHY can't be detected on an Cisco Meraki MR24, if the ethernet cable is not connected on boot. Russell Senior provided steps to reproduce the issue: |Disconnect ethernet cable, apply power, wait until device has booted, |plug in ethernet, check for interfaces, no eth0 is listed. | |This appears to be a problem during probing of the AR8035 Phy chip. |When ethernet has no link, the phy detection fails, and eth0 is not |created. Plugging ethernet later has no effect, because there is no |interface as far as the kernel is concerned. The relevant part of |the boot log looks like this: |this is the failing case: | |[ 0.876611] /plb/opb/emac-rgmii@ef601500: input 0 in RGMII mode |[ 0.882532] /plb/opb/ethernet@ef600c00: reset timeout |[ 0.888546] /plb/opb/ethernet@ef600c00: can't find PHY! |and the succeeding case: | |[ 0.876672] /plb/opb/emac-rgmii@ef601500: input 0 in RGMII mode |[ 0.883952] eth0: EMAC-0 /plb/opb/ethernet@ef600c00, MAC 00:01:.. |[ 0.890822] eth0: found Atheros 8035 Gigabit Ethernet PHY (0x01) Based on the comment and the commit message of commit 23fbb5a87c56 ("emac: Fix EMAC soft reset on 460EX/GT"). This is because the AR8035 PHY doesn't provide the TX Clock, if the ethernet cable is not attached. This causes the reset to timeout and the PHY detection code in emac_init_phy() is unable to detect the AR8035 PHY. As a result, the emac driver bails out early and the user left with no ethernet. In order to stay compatible with existing configurations, the driver tries the current reset approach at first. Only if the first attempt timed out, it does perform one more retry with the clock temporarily switched to the internal source for just the duration of the reset. LEDE-Bug: #687 Cc: Chris Blake Reported-by: Russell Senior Fixes: 23fbb5a87c56e98 ("emac: Fix EMAC soft reset on 460EX/GT") Signed-off-by: Christian Lamparter Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/emac/core.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 508923f39ccf..b6e871bfb659 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -343,6 +343,7 @@ static int emac_reset(struct emac_instance *dev) { struct emac_regs __iomem *p = dev->emacp; int n = 20; + bool __maybe_unused try_internal_clock = false; DBG(dev, "reset" NL); @@ -355,6 +356,7 @@ static int emac_reset(struct emac_instance *dev) } #ifdef CONFIG_PPC_DCR_NATIVE +do_retry: /* * PPC460EX/GT Embedded Processor Advanced User's Manual * section 28.10.1 Mode Register 0 (EMACx_MR0) states: @@ -362,10 +364,19 @@ static int emac_reset(struct emac_instance *dev) * of the EMAC. If none is present, select the internal clock * (SDR0_ETH_CFG[EMACx_PHY_CLK] = 1). * After a soft reset, select the external clock. + * + * The AR8035-A PHY Meraki MR24 does not provide a TX Clk if the + * ethernet cable is not attached. This causes the reset to timeout + * and the PHY detection code in emac_init_phy() is unable to + * communicate and detect the AR8035-A PHY. As a result, the emac + * driver bails out early and the user has no ethernet. + * In order to stay compatible with existing configurations, the + * driver will temporarily switch to the internal clock, after + * the first reset fails. */ if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) { - if (dev->phy_address == 0xffffffff && - dev->phy_map == 0xffffffff) { + if (try_internal_clock || (dev->phy_address == 0xffffffff && + dev->phy_map == 0xffffffff)) { /* No PHY: select internal loop clock before reset */ dcri_clrset(SDR0, SDR0_ETH_CFG, 0, SDR0_ETH_CFG_ECS << dev->cell_index); @@ -383,8 +394,15 @@ static int emac_reset(struct emac_instance *dev) #ifdef CONFIG_PPC_DCR_NATIVE if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) { - if (dev->phy_address == 0xffffffff && - dev->phy_map == 0xffffffff) { + if (!n && !try_internal_clock) { + /* first attempt has timed out. */ + n = 20; + try_internal_clock = true; + goto do_retry; + } + + if (try_internal_clock || (dev->phy_address == 0xffffffff && + dev->phy_map == 0xffffffff)) { /* No PHY: restore external clock source after reset */ dcri_clrset(SDR0, SDR0_ETH_CFG, SDR0_ETH_CFG_ECS << dev->cell_index, 0); From 9065bc386fcf52dee8f697450ddeb788e1bd514c Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 7 Jun 2017 15:51:16 +0200 Subject: [PATCH 14/91] net: emac: fix and unify emac_mdio functions emac_mdio_read_link() was not copying the requested phy settings back into the emac driver's own phy api. This has caused a link speed mismatch issue for the AR8035 as the emac driver kept trying to connect with 10/100MBps on a 1GBit/s link. This patch also unifies shared code between emac_setup_aneg() and emac_mdio_setup_forced(). And furthermore it removes a chunk of emac_mdio_init_phy(), that was copying the same data into itself. Signed-off-by: Christian Lamparter Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/emac/core.c | 41 ++++++++++++---------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index b6e871bfb659..259e69a52ec5 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -2478,20 +2478,24 @@ static int emac_mii_bus_reset(struct mii_bus *bus) return emac_reset(dev); } +static int emac_mdio_phy_start_aneg(struct mii_phy *phy, + struct phy_device *phy_dev) +{ + phy_dev->autoneg = phy->autoneg; + phy_dev->speed = phy->speed; + phy_dev->duplex = phy->duplex; + phy_dev->advertising = phy->advertising; + return phy_start_aneg(phy_dev); +} + static int emac_mdio_setup_aneg(struct mii_phy *phy, u32 advertise) { struct net_device *ndev = phy->dev; struct emac_instance *dev = netdev_priv(ndev); - dev->phy.autoneg = AUTONEG_ENABLE; - dev->phy.speed = SPEED_1000; - dev->phy.duplex = DUPLEX_FULL; - dev->phy.advertising = advertise; phy->autoneg = AUTONEG_ENABLE; - phy->speed = dev->phy.speed; - phy->duplex = dev->phy.duplex; phy->advertising = advertise; - return phy_start_aneg(dev->phy_dev); + return emac_mdio_phy_start_aneg(phy, dev->phy_dev); } static int emac_mdio_setup_forced(struct mii_phy *phy, int speed, int fd) @@ -2499,13 +2503,10 @@ static int emac_mdio_setup_forced(struct mii_phy *phy, int speed, int fd) struct net_device *ndev = phy->dev; struct emac_instance *dev = netdev_priv(ndev); - dev->phy.autoneg = AUTONEG_DISABLE; - dev->phy.speed = speed; - dev->phy.duplex = fd; phy->autoneg = AUTONEG_DISABLE; phy->speed = speed; phy->duplex = fd; - return phy_start_aneg(dev->phy_dev); + return emac_mdio_phy_start_aneg(phy, dev->phy_dev); } static int emac_mdio_poll_link(struct mii_phy *phy) @@ -2527,16 +2528,17 @@ static int emac_mdio_read_link(struct mii_phy *phy) { struct net_device *ndev = phy->dev; struct emac_instance *dev = netdev_priv(ndev); + struct phy_device *phy_dev = dev->phy_dev; int res; - res = phy_read_status(dev->phy_dev); + res = phy_read_status(phy_dev); if (res) return res; - dev->phy.speed = phy->speed; - dev->phy.duplex = phy->duplex; - dev->phy.pause = phy->pause; - dev->phy.asym_pause = phy->asym_pause; + phy->speed = phy_dev->speed; + phy->duplex = phy_dev->duplex; + phy->pause = phy_dev->pause; + phy->asym_pause = phy_dev->asym_pause; return 0; } @@ -2546,13 +2548,6 @@ static int emac_mdio_init_phy(struct mii_phy *phy) struct emac_instance *dev = netdev_priv(ndev); phy_start(dev->phy_dev); - dev->phy.autoneg = phy->autoneg; - dev->phy.speed = phy->speed; - dev->phy.duplex = phy->duplex; - dev->phy.advertising = phy->advertising; - dev->phy.pause = phy->pause; - dev->phy.asym_pause = phy->asym_pause; - return phy_init_hw(dev->phy_dev); } From c164772dd32343ee19e276ce0137830557517834 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 8 Jun 2017 10:50:18 -0400 Subject: [PATCH 15/91] Revert "decnet: dn_rtmsg: Improve input length sanitization in dnrmg_receive_user_skb" This reverts commit 85eac2ba35a2dbfbdd5767c7447a4af07444a5b4. There is an updated version of this fix which we should use instead. Signed-off-by: David S. Miller --- net/decnet/netfilter/dn_rtmsg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c index 26e020e9d415..1ed81ac6dd1a 100644 --- a/net/decnet/netfilter/dn_rtmsg.c +++ b/net/decnet/netfilter/dn_rtmsg.c @@ -102,9 +102,7 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb) { struct nlmsghdr *nlh = nlmsg_hdr(skb); - if (skb->len < sizeof(nlh->nlmsg_len) || - nlh->nlmsg_len < sizeof(*nlh) || - skb->len < nlh->nlmsg_len) + if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) return; if (!netlink_capable(skb, CAP_NET_ADMIN)) From dd0da17b209ed91f39872766634ca967c170ada1 Mon Sep 17 00:00:00 2001 From: Mateusz Jurczyk Date: Wed, 7 Jun 2017 16:14:29 +0200 Subject: [PATCH 16/91] decnet: dn_rtmsg: Improve input length sanitization in dnrmg_receive_user_skb Verify that the length of the socket buffer is sufficient to cover the nlmsghdr structure before accessing the nlh->nlmsg_len field for further input sanitization. If the client only supplies 1-3 bytes of data in sk_buff, then nlh->nlmsg_len remains partially uninitialized and contains leftover memory from the corresponding kernel allocation. Operating on such data may result in indeterminate evaluation of the nlmsg_len < sizeof(*nlh) expression. The bug was discovered by a runtime instrumentation designed to detect use of uninitialized memory in the kernel. The patch prevents this and other similar tools (e.g. KMSAN) from flagging this behavior in the future. Signed-off-by: Mateusz Jurczyk Signed-off-by: David S. Miller --- net/decnet/netfilter/dn_rtmsg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c index 1ed81ac6dd1a..aa8ffecc46a4 100644 --- a/net/decnet/netfilter/dn_rtmsg.c +++ b/net/decnet/netfilter/dn_rtmsg.c @@ -102,7 +102,9 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb) { struct nlmsghdr *nlh = nlmsg_hdr(skb); - if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) + if (skb->len < sizeof(*nlh) || + nlh->nlmsg_len < sizeof(*nlh) || + skb->len < nlh->nlmsg_len) return; if (!netlink_capable(skb, CAP_NET_ADMIN)) From 0eed9cf58446b28b233388b7f224cbca268b6986 Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Wed, 7 Jun 2017 21:00:33 +0300 Subject: [PATCH 17/91] net: Zero ifla_vf_info in rtnl_fill_vfinfo() Some of the structure's fields are not initialized by the rtnetlink. If driver doesn't set those in ndo_get_vf_config(), they'd leak memory to user. Signed-off-by: Yuval Mintz CC: Michal Schmidt Reviewed-by: Greg Rose Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9e2c0a7cb325..5e61456f6bc7 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1124,6 +1124,8 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, struct ifla_vf_mac vf_mac; struct ifla_vf_info ivi; + memset(&ivi, 0, sizeof(ivi)); + /* Not all SR-IOV capable drivers support the * spoofcheck and "RSS query enable" query. Preset to * -1 so the user space tool can detect that the driver @@ -1132,7 +1134,6 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, ivi.spoofchk = -1; ivi.rss_query_en = -1; ivi.trusted = -1; - memset(ivi.mac, 0, sizeof(ivi.mac)); /* The default value for VF link state is "auto" * IFLA_VF_LINK_STATE_AUTO which equals zero */ From 8397ed36b7c585f8d3e06c431f4137309124f78f Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 7 Jun 2017 12:26:23 -0600 Subject: [PATCH 18/91] net: ipv6: Release route when device is unregistering Roopa reported attempts to delete a bond device that is referenced in a multipath route is hanging: $ ifdown bond2 # ifupdown2 command that deletes virtual devices unregister_netdevice: waiting for bond2 to become free. Usage count = 2 Steps to reproduce: echo 1 > /proc/sys/net/ipv6/conf/all/ignore_routes_with_linkdown ip link add dev bond12 type bond ip link add dev bond13 type bond ip addr add 2001:db8:2::0/64 dev bond12 ip addr add 2001:db8:3::0/64 dev bond13 ip route add 2001:db8:33::0/64 nexthop via 2001:db8:2::2 nexthop via 2001:db8:3::2 ip link del dev bond12 ip link del dev bond13 The root cause is the recent change to keep routes on a linkdown. Update the check to detect when the device is unregistering and release the route for that case. Fixes: a1a22c12060e4 ("net: ipv6: Keep nexthop of multipath route on admin down") Reported-by: Roopa Prabhu Signed-off-by: David Ahern Acked-by: Roopa Prabhu Signed-off-by: David S. Miller --- include/linux/netdevice.h | 5 +++++ net/ipv6/route.c | 1 + 2 files changed, 6 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ab7ca3fdc495..846193dfb0ac 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -4262,6 +4262,11 @@ static inline const char *netdev_name(const struct net_device *dev) return dev->name; } +static inline bool netdev_unregistering(const struct net_device *dev) +{ + return dev->reg_state == NETREG_UNREGISTERING; +} + static inline const char *netdev_reg_state(const struct net_device *dev) { switch (dev->reg_state) { diff --git a/net/ipv6/route.c b/net/ipv6/route.c index dc61b0b5e64e..7cebd954d5bb 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2804,6 +2804,7 @@ static int fib6_ifdown(struct rt6_info *rt, void *arg) if ((rt->dst.dev == dev || !dev) && rt != adn->net->ipv6.ip6_null_entry && (rt->rt6i_nsiblings == 0 || + (dev && netdev_unregistering(dev)) || !rt->rt6i_idev->cnf.ignore_routes_with_linkdown)) return -1; From fbd4c7e768f1719bea340e40148800279d230922 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 7 Jun 2017 15:53:47 -0700 Subject: [PATCH 19/91] netvsc: fix rcu dereference warning from ethtool The ethtool info command calls the netvsc get_sset_count with RTNL but not with RCU. Which causes warning: drivers/net/hyperv/netvsc_drv.c:1010 suspicious rcu_dereference_check() usage! Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 4421a6d00375..d93e4da25fd2 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -1028,7 +1028,7 @@ static const struct { static int netvsc_get_sset_count(struct net_device *dev, int string_set) { struct net_device_context *ndc = netdev_priv(dev); - struct netvsc_device *nvdev = rcu_dereference(ndc->nvdev); + struct netvsc_device *nvdev = rtnl_dereference(ndc->nvdev); if (!nvdev) return -ENODEV; From a5ecd43992a7cd9f91d5f98b0082ae44df5e543c Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 7 Jun 2017 15:53:48 -0700 Subject: [PATCH 20/91] netvsc: fix net poll mode The ndo_poll_controller function needs to schedule NAPI to pick up arriving packets and send completions. Otherwise no data will ever be received. For simple case of netconsole, it also will allow send completions to happen. Without this netpoll will eventually get stuck. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc_drv.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index d93e4da25fd2..252e5d52d17e 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -1158,11 +1158,22 @@ netvsc_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, } #ifdef CONFIG_NET_POLL_CONTROLLER -static void netvsc_poll_controller(struct net_device *net) +static void netvsc_poll_controller(struct net_device *dev) { - /* As netvsc_start_xmit() works synchronous we don't have to - * trigger anything here. - */ + struct net_device_context *ndc = netdev_priv(dev); + struct netvsc_device *ndev; + int i; + + rcu_read_lock(); + ndev = rcu_dereference(ndc->nvdev); + if (ndev) { + for (i = 0; i < ndev->num_chn; i++) { + struct netvsc_channel *nvchan = &ndev->chan_table[i]; + + napi_schedule(&nvchan->napi); + } + } + rcu_read_unlock(); } #endif From 4f19c0d8070cd4aa8e85bbf8a19d9ef5bef77c90 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 7 Jun 2017 15:53:49 -0700 Subject: [PATCH 21/91] netvsc: move filter setting to rndis_device The work queue and handling of network filter parameters should be in rndis_device. This gets rid of warning from RCU checks, eliminates a race and cleans up code. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 5 +++-- drivers/net/hyperv/netvsc_drv.c | 33 ++----------------------------- drivers/net/hyperv/rndis_filter.c | 30 +++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 262b2ea576a3..6066f1bcaf2d 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -171,6 +171,8 @@ struct rndis_device { spinlock_t request_lock; struct list_head req_list; + struct work_struct mcast_work; + u8 hw_mac_adr[ETH_ALEN]; u8 rss_key[NETVSC_HASH_KEYLEN]; u16 ind_table[ITAB_NUM]; @@ -201,6 +203,7 @@ int rndis_filter_open(struct netvsc_device *nvdev); int rndis_filter_close(struct netvsc_device *nvdev); int rndis_filter_device_add(struct hv_device *dev, struct netvsc_device_info *info); +void rndis_filter_update(struct netvsc_device *nvdev); void rndis_filter_device_remove(struct hv_device *dev, struct netvsc_device *nvdev); int rndis_filter_set_rss_param(struct rndis_device *rdev, @@ -211,7 +214,6 @@ int rndis_filter_receive(struct net_device *ndev, struct vmbus_channel *channel, void *data, u32 buflen); -int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter); int rndis_filter_set_device_mac(struct net_device *ndev, char *mac); void netvsc_switch_datapath(struct net_device *nv_dev, bool vf); @@ -696,7 +698,6 @@ struct net_device_context { /* list protection */ spinlock_t lock; - struct work_struct work; u32 msg_enable; /* debug level */ u32 tx_checksum_mask; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 252e5d52d17e..82d6c022ca85 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -56,37 +56,12 @@ static int debug = -1; module_param(debug, int, S_IRUGO); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -static void do_set_multicast(struct work_struct *w) -{ - struct net_device_context *ndevctx = - container_of(w, struct net_device_context, work); - struct hv_device *device_obj = ndevctx->device_ctx; - struct net_device *ndev = hv_get_drvdata(device_obj); - struct netvsc_device *nvdev = rcu_dereference(ndevctx->nvdev); - struct rndis_device *rdev; - - if (!nvdev) - return; - - rdev = nvdev->extension; - if (rdev == NULL) - return; - - if (ndev->flags & IFF_PROMISC) - rndis_filter_set_packet_filter(rdev, - NDIS_PACKET_TYPE_PROMISCUOUS); - else - rndis_filter_set_packet_filter(rdev, - NDIS_PACKET_TYPE_BROADCAST | - NDIS_PACKET_TYPE_ALL_MULTICAST | - NDIS_PACKET_TYPE_DIRECTED); -} - static void netvsc_set_multicast_list(struct net_device *net) { struct net_device_context *net_device_ctx = netdev_priv(net); + struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev); - schedule_work(&net_device_ctx->work); + rndis_filter_update(nvdev); } static int netvsc_open(struct net_device *net) @@ -123,8 +98,6 @@ static int netvsc_close(struct net_device *net) netif_tx_disable(net); - /* Make sure netvsc_set_multicast_list doesn't re-enable filter! */ - cancel_work_sync(&net_device_ctx->work); ret = rndis_filter_close(nvdev); if (ret != 0) { netdev_err(net, "unable to close device (ret %d).\n", ret); @@ -1563,7 +1536,6 @@ static int netvsc_probe(struct hv_device *dev, hv_set_drvdata(dev, net); INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change); - INIT_WORK(&net_device_ctx->work, do_set_multicast); spin_lock_init(&net_device_ctx->lock); INIT_LIST_HEAD(&net_device_ctx->reconfig_events); @@ -1633,7 +1605,6 @@ static int netvsc_remove(struct hv_device *dev) netif_device_detach(net); cancel_delayed_work_sync(&ndev_ctx->dwork); - cancel_work_sync(&ndev_ctx->work); /* * Call to the vsc driver to let it know that the device is being diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index f9d5b0b8209a..cb79cd081f42 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -31,6 +31,7 @@ #include "hyperv_net.h" +static void rndis_set_multicast(struct work_struct *w); #define RNDIS_EXT_LEN PAGE_SIZE struct rndis_request { @@ -76,6 +77,7 @@ static struct rndis_device *get_rndis_device(void) spin_lock_init(&device->request_lock); INIT_LIST_HEAD(&device->req_list); + INIT_WORK(&device->mcast_work, rndis_set_multicast); device->state = RNDIS_DEV_UNINITIALIZED; @@ -815,7 +817,8 @@ static int rndis_filter_query_link_speed(struct rndis_device *dev) return ret; } -int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter) +static int rndis_filter_set_packet_filter(struct rndis_device *dev, + u32 new_filter) { struct rndis_request *request; struct rndis_set_request *set; @@ -846,6 +849,28 @@ int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter) return ret; } +static void rndis_set_multicast(struct work_struct *w) +{ + struct rndis_device *rdev + = container_of(w, struct rndis_device, mcast_work); + + if (rdev->ndev->flags & IFF_PROMISC) + rndis_filter_set_packet_filter(rdev, + NDIS_PACKET_TYPE_PROMISCUOUS); + else + rndis_filter_set_packet_filter(rdev, + NDIS_PACKET_TYPE_BROADCAST | + NDIS_PACKET_TYPE_ALL_MULTICAST | + NDIS_PACKET_TYPE_DIRECTED); +} + +void rndis_filter_update(struct netvsc_device *nvdev) +{ + struct rndis_device *rdev = nvdev->extension; + + schedule_work(&rdev->mcast_work); +} + static int rndis_filter_init_device(struct rndis_device *dev) { struct rndis_request *request; @@ -973,6 +998,9 @@ static int rndis_filter_close_device(struct rndis_device *dev) if (dev->state != RNDIS_DEV_DATAINITIALIZED) return 0; + /* Make sure rndis_set_multicast doesn't re-enable filter! */ + cancel_work_sync(&dev->mcast_work); + ret = rndis_filter_set_packet_filter(dev, 0); if (ret == -ENODEV) ret = 0; From 0bed865060836dc5f26b68052de0a504d66d9fae Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 8 Jun 2017 11:51:59 -0400 Subject: [PATCH 22/91] net: Fix build regression in rtl8723bs staging driver. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c: In function ‘rtw_cfg80211_add_monitor_if’: drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c:2670:10: error: ‘struct net_device’ has no member named ‘destructor’ mon_ndev->destructor = rtw_ndev_destructor; ^ Signed-off-by: David S. Miller --- drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 3 ++- drivers/staging/rtl8723bs/os_dep/os_intfs.c | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 36c3189fc4b7..bd4352fe2de3 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -2667,7 +2667,8 @@ static int rtw_cfg80211_add_monitor_if (struct adapter *padapter, char *name, st mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP; strncpy(mon_ndev->name, name, IFNAMSIZ); mon_ndev->name[IFNAMSIZ - 1] = 0; - mon_ndev->destructor = rtw_ndev_destructor; + mon_ndev->needs_free_netdev = true; + mon_ndev->priv_destructor = rtw_ndev_destructor; mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops; diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index f83cfc76505c..021589913681 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c @@ -1207,8 +1207,6 @@ void rtw_ndev_destructor(struct net_device *ndev) if (ndev->ieee80211_ptr) kfree((u8 *)ndev->ieee80211_ptr); - - free_netdev(ndev); } void rtw_dev_unload(struct adapter *padapter) From 0db47e3d323411beeb6ea97f2c4d19395c91fd8b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 8 Jun 2017 09:54:24 +0200 Subject: [PATCH 23/91] ila_xlat: add missing hash secret initialization While discussing the possible merits of clang warning about unused initialized functions, I found one function that was clearly meant to be called but never actually is. __ila_hash_secret_init() initializes the hash value for the ila locator, apparently this is intended to prevent hash collision attacks, but this ends up being a read-only zero constant since there is no caller. I could find no indication of why it was never called, the earliest patch submission for the module already was like this. If my interpretation is right, we certainly want to backport the patch to stable kernels as well. I considered adding it to the ila_xlat_init callback, but for best effect the random data is read as late as possible, just before it is first used. The underlying net_get_random_once() is already highly optimized to avoid overhead when called frequently. Fixes: 7f00feaf1076 ("ila: Add generic ILA translation facility") Cc: stable@vger.kernel.org Link: https://www.spinics.net/lists/kernel/msg2527243.html Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- net/ipv6/ila/ila_xlat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 2fd5ca151dcf..77f7f8c7d93d 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -62,6 +62,7 @@ static inline u32 ila_locator_hash(struct ila_locator loc) { u32 *v = (u32 *)loc.v32; + __ila_hash_secret_init(); return jhash_2words(v[0], v[1], hashrnd); } From daa6630a310fe2ad90ce5f7d2d196cd0353ef4fa Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 8 Jun 2017 10:37:45 +0200 Subject: [PATCH 24/91] openvswitch: warn about missing first netlink attribute The first netlink attribute (value 0) must always be defined as none/unspec. Because we cannot change an existing UAPI, I add a comment to point the mistake and avoid to propagate it in a new ovs API in the future. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/openvswitch.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h index 61b7d36dfe34..156ee4cab82e 100644 --- a/include/uapi/linux/openvswitch.h +++ b/include/uapi/linux/openvswitch.h @@ -343,6 +343,7 @@ enum ovs_key_attr { #define OVS_KEY_ATTR_MAX (__OVS_KEY_ATTR_MAX - 1) enum ovs_tunnel_key_attr { + /* OVS_TUNNEL_KEY_ATTR_NONE, standard nl API requires this attribute! */ OVS_TUNNEL_KEY_ATTR_ID, /* be64 Tunnel ID */ OVS_TUNNEL_KEY_ATTR_IPV4_SRC, /* be32 src IP address. */ OVS_TUNNEL_KEY_ATTR_IPV4_DST, /* be32 dst IP address. */ From c7c550670afda2e16f9e2d06a1473885312eb6b5 Mon Sep 17 00:00:00 2001 From: Thibaut Collet Date: Thu, 8 Jun 2017 11:18:11 +0200 Subject: [PATCH 25/91] bonding: fix 802.3ad support for 5G and 50G speeds This patch adds [5|50] Gbps enum definition, and fixes aggregated bandwidth calculation based on above slave links. Fixes: c9a70d43461d ("net-next: ethtool: Added port speed macros.") Signed-off-by: Thibaut Collet Signed-off-by: Nicolas Dichtel Acked-by: Andy Gospodarek Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index b44a6aeb346d..d1b09be63ba4 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -90,10 +90,12 @@ enum ad_link_speed_type { AD_LINK_SPEED_100MBPS, AD_LINK_SPEED_1000MBPS, AD_LINK_SPEED_2500MBPS, + AD_LINK_SPEED_5000MBPS, AD_LINK_SPEED_10000MBPS, AD_LINK_SPEED_20000MBPS, AD_LINK_SPEED_25000MBPS, AD_LINK_SPEED_40000MBPS, + AD_LINK_SPEED_50000MBPS, AD_LINK_SPEED_56000MBPS, AD_LINK_SPEED_100000MBPS, }; @@ -259,10 +261,12 @@ static inline int __check_agg_selection_timer(struct port *port) * %AD_LINK_SPEED_100MBPS, * %AD_LINK_SPEED_1000MBPS, * %AD_LINK_SPEED_2500MBPS, + * %AD_LINK_SPEED_5000MBPS, * %AD_LINK_SPEED_10000MBPS * %AD_LINK_SPEED_20000MBPS * %AD_LINK_SPEED_25000MBPS * %AD_LINK_SPEED_40000MBPS + * %AD_LINK_SPEED_50000MBPS * %AD_LINK_SPEED_56000MBPS * %AD_LINK_SPEED_100000MBPS */ @@ -296,6 +300,10 @@ static u16 __get_link_speed(struct port *port) speed = AD_LINK_SPEED_2500MBPS; break; + case SPEED_5000: + speed = AD_LINK_SPEED_5000MBPS; + break; + case SPEED_10000: speed = AD_LINK_SPEED_10000MBPS; break; @@ -312,6 +320,10 @@ static u16 __get_link_speed(struct port *port) speed = AD_LINK_SPEED_40000MBPS; break; + case SPEED_50000: + speed = AD_LINK_SPEED_50000MBPS; + break; + case SPEED_56000: speed = AD_LINK_SPEED_56000MBPS; break; @@ -707,6 +719,9 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator) case AD_LINK_SPEED_2500MBPS: bandwidth = nports * 2500; break; + case AD_LINK_SPEED_5000MBPS: + bandwidth = nports * 5000; + break; case AD_LINK_SPEED_10000MBPS: bandwidth = nports * 10000; break; @@ -719,6 +734,9 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator) case AD_LINK_SPEED_40000MBPS: bandwidth = nports * 40000; break; + case AD_LINK_SPEED_50000MBPS: + bandwidth = nports * 50000; + break; case AD_LINK_SPEED_56000MBPS: bandwidth = nports * 56000; break; From 3fcd64cfa0e9cb72b99aaba5c6bc13af9c03417f Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 8 Jun 2017 11:18:12 +0200 Subject: [PATCH 26/91] bonding: fix 802.3ad support for 14G speed This patch adds 14 Gbps enum definition, and fixes aggregated bandwidth calculation based on above slave links. Fixes: 0d7e2d2166f6 ("IB/ipoib: add get_link_ksettings in ethtool") Signed-off-by: Nicolas Dichtel Acked-by: Andy Gospodarek Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index d1b09be63ba4..e5386ab706ec 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -92,6 +92,7 @@ enum ad_link_speed_type { AD_LINK_SPEED_2500MBPS, AD_LINK_SPEED_5000MBPS, AD_LINK_SPEED_10000MBPS, + AD_LINK_SPEED_14000MBPS, AD_LINK_SPEED_20000MBPS, AD_LINK_SPEED_25000MBPS, AD_LINK_SPEED_40000MBPS, @@ -263,6 +264,7 @@ static inline int __check_agg_selection_timer(struct port *port) * %AD_LINK_SPEED_2500MBPS, * %AD_LINK_SPEED_5000MBPS, * %AD_LINK_SPEED_10000MBPS + * %AD_LINK_SPEED_14000MBPS, * %AD_LINK_SPEED_20000MBPS * %AD_LINK_SPEED_25000MBPS * %AD_LINK_SPEED_40000MBPS @@ -308,6 +310,10 @@ static u16 __get_link_speed(struct port *port) speed = AD_LINK_SPEED_10000MBPS; break; + case SPEED_14000: + speed = AD_LINK_SPEED_14000MBPS; + break; + case SPEED_20000: speed = AD_LINK_SPEED_20000MBPS; break; @@ -725,6 +731,9 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator) case AD_LINK_SPEED_10000MBPS: bandwidth = nports * 10000; break; + case AD_LINK_SPEED_14000MBPS: + bandwidth = nports * 14000; + break; case AD_LINK_SPEED_20000MBPS: bandwidth = nports * 20000; break; From 297fb414d0d190ca82bf0b46fb19d7fda1598737 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 8 Jun 2017 11:18:13 +0200 Subject: [PATCH 27/91] ethtool.h: remind to update 802.3ad when adding new speeds Each time a new speed is added, the bonding 802.3ad isn't updated. Add a comment to remind the developer to update this driver. Signed-off-by: Nicolas Dichtel Acked-by: Andy Gospodarek Signed-off-by: David S. Miller --- include/uapi/linux/ethtool.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index d179d7767f51..7d4a594d5d58 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -1486,8 +1486,10 @@ enum ethtool_link_mode_bit_indices { * it was forced up into this mode or autonegotiated. */ -/* The forced speed, in units of 1Mb. All values 0 to INT_MAX are legal. */ -/* Update drivers/net/phy/phy.c:phy_speed_to_str() when adding new values */ +/* The forced speed, in units of 1Mb. All values 0 to INT_MAX are legal. + * Update drivers/net/phy/phy.c:phy_speed_to_str() and + * drivers/net/bonding/bond_3ad.c:__get_link_speed() when adding new values. + */ #define SPEED_10 10 #define SPEED_100 100 #define SPEED_1000 1000 From 78a5a93c1eeb4e6933d1f62b33e5496d53b46c5a Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 8 Jun 2017 19:06:25 +0200 Subject: [PATCH 28/91] bpf, tests: fix endianness selection I noticed that test_l4lb was failing in selftests: # ./test_progs test_pkt_access:PASS:ipv4 77 nsec test_pkt_access:PASS:ipv6 44 nsec test_xdp:PASS:ipv4 2933 nsec test_xdp:PASS:ipv6 1500 nsec test_l4lb:PASS:ipv4 377 nsec test_l4lb:PASS:ipv6 544 nsec test_l4lb:FAIL:stats 6297600000 200000 test_tcp_estats:PASS: 0 nsec Summary: 7 PASSED, 1 FAILED Tracking down the issue actually revealed that endianness selection in bpf_endian.h is broken when compiled with clang with bpf target. test_pkt_access.c, test_l4lb.c is compiled with __BYTE_ORDER as __BIG_ENDIAN, test_xdp.c as __LITTLE_ENDIAN! test_l4lb noticeably fails, because the test accounts bytes via bpf_ntohs(ip6h->payload_len) and bpf_ntohs(iph->tot_len), and compares them against a defined value and given a wrong endianness, the test outcome is different, of course. Turns out that there are actually two bugs: i) when we do __BYTE_ORDER comparison with __LITTLE_ENDIAN/__BIG_ENDIAN, then depending on the include order we see different outcomes. Reason is that __BYTE_ORDER is undefined due to missing endian.h include. Before we include the asm/byteorder.h (e.g. through linux/in.h), then __BYTE_ORDER equals __LITTLE_ENDIAN since both are undefined, after the include which correctly pulls in linux/byteorder/little_endian.h, __LITTLE_ENDIAN is defined, but given __BYTE_ORDER is still undefined, we match on __BYTE_ORDER equals to __BIG_ENDIAN since __BIG_ENDIAN is also undefined at that point, sigh. ii) But even that would be wrong, since when compiling the test cases with clang, one can select between bpfeb and bpfel targets for cross compilation. Hence, we can also not rely on what the system's endian.h provides, but we need to look at the compiler's defined endianness. The compiler defines __BYTE_ORDER__, and we can match __ORDER_LITTLE_ENDIAN__ and __ORDER_BIG_ENDIAN__, which also reflects targets bpf (native), bpfel, bpfeb correctly, thus really only rely on that. After patch: # ./test_progs test_pkt_access:PASS:ipv4 74 nsec test_pkt_access:PASS:ipv6 42 nsec test_xdp:PASS:ipv4 2340 nsec test_xdp:PASS:ipv6 1461 nsec test_l4lb:PASS:ipv4 400 nsec test_l4lb:PASS:ipv6 530 nsec test_tcp_estats:PASS: 0 nsec Summary: 7 PASSED, 0 FAILED Fixes: 43bcf707ccdc ("bpf: fix _htons occurences in test_progs") Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- tools/testing/selftests/bpf/bpf_endian.h | 41 +++++++++++++++++------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/tools/testing/selftests/bpf/bpf_endian.h b/tools/testing/selftests/bpf/bpf_endian.h index 19d0604f8694..487cbfb89beb 100644 --- a/tools/testing/selftests/bpf/bpf_endian.h +++ b/tools/testing/selftests/bpf/bpf_endian.h @@ -1,23 +1,42 @@ #ifndef __BPF_ENDIAN__ #define __BPF_ENDIAN__ -#include +#include -#if __BYTE_ORDER == __LITTLE_ENDIAN -# define __bpf_ntohs(x) __builtin_bswap16(x) -# define __bpf_htons(x) __builtin_bswap16(x) -#elif __BYTE_ORDER == __BIG_ENDIAN -# define __bpf_ntohs(x) (x) -# define __bpf_htons(x) (x) +/* LLVM's BPF target selects the endianness of the CPU + * it compiles on, or the user specifies (bpfel/bpfeb), + * respectively. The used __BYTE_ORDER__ is defined by + * the compiler, we cannot rely on __BYTE_ORDER from + * libc headers, since it doesn't reflect the actual + * requested byte order. + * + * Note, LLVM's BPF target has different __builtin_bswapX() + * semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE + * in bpfel and bpfeb case, which means below, that we map + * to cpu_to_be16(). We could use it unconditionally in BPF + * case, but better not rely on it, so that this header here + * can be used from application and BPF program side, which + * use different targets. + */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define __bpf_ntohs(x) __builtin_bswap16(x) +# define __bpf_htons(x) __builtin_bswap16(x) +# define __bpf_constant_ntohs(x) ___constant_swab16(x) +# define __bpf_constant_htons(x) ___constant_swab16(x) +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define __bpf_ntohs(x) (x) +# define __bpf_htons(x) (x) +# define __bpf_constant_ntohs(x) (x) +# define __bpf_constant_htons(x) (x) #else -# error "Fix your __BYTE_ORDER?!" +# error "Fix your compiler's __BYTE_ORDER__?!" #endif #define bpf_htons(x) \ (__builtin_constant_p(x) ? \ - __constant_htons(x) : __bpf_htons(x)) + __bpf_constant_htons(x) : __bpf_htons(x)) #define bpf_ntohs(x) \ (__builtin_constant_p(x) ? \ - __constant_ntohs(x) : __bpf_ntohs(x)) + __bpf_constant_ntohs(x) : __bpf_ntohs(x)) -#endif +#endif /* __BPF_ENDIAN__ */ From 097d3c9508dc58286344e4a22b300098cf0c1566 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 8 Jun 2017 11:31:11 -0600 Subject: [PATCH 29/91] net: vrf: Make add_fib_rules per network namespace flag Commit 1aa6c4f6b8cd8 ("net: vrf: Add l3mdev rules on first device create") adds the l3mdev FIB rule the first time a VRF device is created. However, it only creates the rule once and only in the namespace the first device is created - which may not be init_net. Fix by using the net_generic capability to make the add_fib_rules flag per network namespace. Fixes: 1aa6c4f6b8cd8 ("net: vrf: Add l3mdev rules on first device create") Reported-by: Petr Machata Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index d38f11d833fe..022c0b5f9844 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -36,12 +36,14 @@ #include #include #include +#include #define DRV_NAME "vrf" #define DRV_VERSION "1.0" #define FIB_RULE_PREF 1000 /* default preference for FIB rules */ -static bool add_fib_rules = true; + +static unsigned int vrf_net_id; struct net_vrf { struct rtable __rcu *rth; @@ -1394,6 +1396,8 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { struct net_vrf *vrf = netdev_priv(dev); + bool *add_fib_rules; + struct net *net; int err; if (!data || !data[IFLA_VRF_TABLE]) @@ -1409,13 +1413,15 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev, if (err) goto out; - if (add_fib_rules) { + net = dev_net(dev); + add_fib_rules = net_generic(net, vrf_net_id); + if (*add_fib_rules) { err = vrf_add_fib_rules(dev); if (err) { unregister_netdevice(dev); goto out; } - add_fib_rules = false; + *add_fib_rules = false; } out: @@ -1498,16 +1504,38 @@ static struct notifier_block vrf_notifier_block __read_mostly = { .notifier_call = vrf_device_event, }; +/* Initialize per network namespace state */ +static int __net_init vrf_netns_init(struct net *net) +{ + bool *add_fib_rules = net_generic(net, vrf_net_id); + + *add_fib_rules = true; + + return 0; +} + +static struct pernet_operations vrf_net_ops __net_initdata = { + .init = vrf_netns_init, + .id = &vrf_net_id, + .size = sizeof(bool), +}; + static int __init vrf_init_module(void) { int rc; register_netdevice_notifier(&vrf_notifier_block); - rc = rtnl_link_register(&vrf_link_ops); + rc = register_pernet_subsys(&vrf_net_ops); if (rc < 0) goto error; + rc = rtnl_link_register(&vrf_link_ops); + if (rc < 0) { + unregister_pernet_subsys(&vrf_net_ops); + goto error; + } + return 0; error: From ff3416fb5b02cfae94591ef4395b0b4dc793f25e Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 18 May 2017 10:22:22 +0200 Subject: [PATCH 30/91] can: dev: make can_change_state() robust to be called with cf == NULL In OOM situations where no skb can be allocated, can_change_state() may be called with cf == NULL. As this function updates the state and error statistics it's not an option to skip the call to can_change_state() in OOM situations. This patch makes can_change_state() robust, so that it can be called with cf == NULL. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/dev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 611d16a7061d..ae4ed03dc642 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -391,6 +391,9 @@ void can_change_state(struct net_device *dev, struct can_frame *cf, can_update_state_error_stats(dev, new_state); priv->state = new_state; + if (!cf) + return; + if (unlikely(new_state == CAN_STATE_BUS_OFF)) { cf->can_id |= CAN_ERR_BUSOFF; return; From f2a918b40cea994f9524ace67fd05ef42a8d9e5b Mon Sep 17 00:00:00 2001 From: Stephane Grosjean Date: Wed, 3 May 2017 10:35:04 +0200 Subject: [PATCH 31/91] can: peak_canfd: fix uninitialized symbol warnings This patch fixes two uninitialized symbol warnings in the new code adding support of the PEAK-System PCAN-PCI Express FD boards, in the socket-CAN network protocol family. Signed-off-by: Stephane Grosjean Reported-by: Dan Carpenter Signed-off-by: Marc Kleine-Budde --- drivers/net/can/peak_canfd/peak_canfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c index 0d57be5ea97b..85268be0c913 100644 --- a/drivers/net/can/peak_canfd/peak_canfd.c +++ b/drivers/net/can/peak_canfd/peak_canfd.c @@ -489,7 +489,7 @@ int peak_canfd_handle_msgs_list(struct peak_canfd_priv *priv, struct pucan_rx_msg *msg_list, int msg_count) { void *msg_ptr = msg_list; - int i, msg_size; + int i, msg_size = 0; for (i = 0; i < msg_count; i++) { msg_size = peak_canfd_handle_msg(priv, msg_ptr); From dadcd398b3f059a0aa9de1cac8030a1d5a3791a5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 12 May 2017 12:09:25 +0200 Subject: [PATCH 32/91] can: peak_usb: fix product-id endianness in error message Make sure to use the USB device product-id stored in host-byte order in a probe error message. Also remove a redundant reassignment of the local usb_dev variable which had already been used to retrieve the product id. Signed-off-by: Johan Hovold Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index 57913dbbae0a..1ca76e03e965 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -908,8 +908,6 @@ static int peak_usb_probe(struct usb_interface *intf, const struct peak_usb_adapter *peak_usb_adapter = NULL; int i, err = -ENOMEM; - usb_dev = interface_to_usbdev(intf); - /* get corresponding PCAN-USB adapter */ for (i = 0; i < ARRAY_SIZE(peak_usb_adapters_list); i++) if (peak_usb_adapters_list[i]->device_id == usb_id_product) { @@ -920,7 +918,7 @@ static int peak_usb_probe(struct usb_interface *intf, if (!peak_usb_adapter) { /* should never come except device_id bad usage in this file */ pr_err("%s: didn't find device id. 0x%x in devices list\n", - PCAN_USB_DRIVER_NAME, usb_dev->descriptor.idProduct); + PCAN_USB_DRIVER_NAME, usb_id_product); return -ENODEV; } From 5cda3ee5138e91ac369ed9d0b55eab0dab077686 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sun, 4 Jun 2017 14:03:42 +0200 Subject: [PATCH 33/91] can: gs_usb: fix memory leak in gs_cmd_reset() This patch adds the missing kfree() in gs_cmd_reset() to free the memory that is not used anymore after usb_control_msg(). Cc: linux-stable Cc: Maximilian Schneider Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index eecee7f8dfb7..afcc1312dbaf 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -265,6 +265,8 @@ static int gs_cmd_reset(struct gs_usb *gsusb, struct gs_can *gsdev) sizeof(*dm), 1000); + kfree(dm); + return rc; } From 74b7b490886852582d986a33443c2ffa50970169 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 6 Jun 2017 13:53:16 +0200 Subject: [PATCH 34/91] can: af_can: namespace support: fix lockdep splat: properly initialize spin_lock This patch uses spin_lock_init() instead of __SPIN_LOCK_UNLOCKED() to initialize the per namespace net->can.can_rcvlists_lock lock to fix this lockdep warning: | INFO: trying to register non-static key. | the code is fine but needs lockdep annotation. | turning off the locking correctness validator. | CPU: 0 PID: 186 Comm: candump Not tainted 4.12.0-rc3+ #47 | Hardware name: Marvell Kirkwood (Flattened Device Tree) | [] (unwind_backtrace) from [] (show_stack+0x18/0x1c) | [] (show_stack) from [] (register_lock_class+0x1e4/0x55c) | [] (register_lock_class) from [] (__lock_acquire+0x148/0x1990) | [] (__lock_acquire) from [] (lock_acquire+0x174/0x210) | [] (lock_acquire) from [] (_raw_spin_lock+0x50/0x88) | [] (_raw_spin_lock) from [] (can_rx_register+0x94/0x15c [can]) | [] (can_rx_register [can]) from [] (raw_enable_filters+0x60/0xc0 [can_raw]) | [] (raw_enable_filters [can_raw]) from [] (raw_enable_allfilters+0x2c/0xa0 [can_raw]) | [] (raw_enable_allfilters [can_raw]) from [] (raw_bind+0xb0/0x250 [can_raw]) | [] (raw_bind [can_raw]) from [] (SyS_bind+0x70/0xac) | [] (SyS_bind) from [] (ret_fast_syscall+0x0/0x1c) Cc: Mario Kicherer Acked-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- net/can/af_can.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/can/af_can.c b/net/can/af_can.c index b6406fe33c76..88edac0f3e36 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -872,8 +872,7 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg, static int can_pernet_init(struct net *net) { - net->can.can_rcvlists_lock = - __SPIN_LOCK_UNLOCKED(net->can.can_rcvlists_lock); + spin_lock_init(&net->can.can_rcvlists_lock); net->can.can_rx_alldev_list = kzalloc(sizeof(struct dev_rcv_lists), GFP_KERNEL); From 97edec3a11cf6f73f2e45c3035b5ff8e4c3543dd Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Fri, 2 Jun 2017 19:37:30 +0200 Subject: [PATCH 35/91] can: enable CAN FD for virtual CAN devices by default CAN FD capable CAN interfaces can handle (classic) CAN 2.0 frames too. New users usually fail at their first attempt to explore CAN FD on virtual CAN interfaces due to the current CAN_MTU default. Set the MTU to CANFD_MTU by default to reduce this confusion. If someone *really* needs a 'classic CAN'-only device this can be set with the 'ip' tool with e.g. 'ip link set vcan0 mtu 16' as before. Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- drivers/net/can/vcan.c | 2 +- drivers/net/can/vxcan.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 0eda1b308583..a8cb33264ff1 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -152,7 +152,7 @@ static const struct net_device_ops vcan_netdev_ops = { static void vcan_setup(struct net_device *dev) { dev->type = ARPHRD_CAN; - dev->mtu = CAN_MTU; + dev->mtu = CANFD_MTU; dev->hard_header_len = 0; dev->addr_len = 0; dev->tx_queue_len = 0; diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index 30cf2368becf..cfe889e8f172 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -150,7 +150,7 @@ static const struct net_device_ops vxcan_netdev_ops = { static void vxcan_setup(struct net_device *dev) { dev->type = ARPHRD_CAN; - dev->mtu = CAN_MTU; + dev->mtu = CANFD_MTU; dev->hard_header_len = 0; dev->addr_len = 0; dev->tx_queue_len = 0; From fc5b775da468e359154795afeb27be79b509b76d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 9 Jun 2017 15:45:32 +0200 Subject: [PATCH 36/91] net: phy: add missing SPEED_14000 Fixes: 0d7e2d2166f6 ("IB/ipoib: add get_link_ksettings in ethtool") Signed-off-by: Joe Perches Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 7524caa0f29d..eebb0e1c70ff 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -54,6 +54,8 @@ static const char *phy_speed_to_str(int speed) return "5Gbps"; case SPEED_10000: return "10Gbps"; + case SPEED_14000: + return "14Gbps"; case SPEED_20000: return "20Gbps"; case SPEED_25000: From defbcf2decc903a28d8398aa477b6881e711e3ea Mon Sep 17 00:00:00 2001 From: Mateusz Jurczyk Date: Thu, 8 Jun 2017 11:13:36 +0200 Subject: [PATCH 37/91] af_unix: Add sockaddr length checks before accessing sa_family in bind and connect handlers Verify that the caller-provided sockaddr structure is large enough to contain the sa_family field, before accessing it in bind() and connect() handlers of the AF_UNIX socket. Since neither syscall enforces a minimum size of the corresponding memory region, very short sockaddrs (zero or one byte long) result in operating on uninitialized memory while referencing .sa_family. Signed-off-by: Mateusz Jurczyk Signed-off-by: David S. Miller --- net/unix/af_unix.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 6a7fe7660551..1a0c961f4ffe 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -999,7 +999,8 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct path path = { }; err = -EINVAL; - if (sunaddr->sun_family != AF_UNIX) + if (addr_len < offsetofend(struct sockaddr_un, sun_family) || + sunaddr->sun_family != AF_UNIX) goto out; if (addr_len == sizeof(short)) { @@ -1110,6 +1111,10 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, unsigned int hash; int err; + err = -EINVAL; + if (alen < offsetofend(struct sockaddr, sa_family)) + goto out; + if (addr->sa_family != AF_UNSPEC) { err = unix_mkname(sunaddr, alen, &hash); if (err < 0) From f186ce61bb8235d80068c390dc2aad7ca427a4c2 Mon Sep 17 00:00:00 2001 From: Krister Johansen Date: Thu, 8 Jun 2017 13:12:38 -0700 Subject: [PATCH 38/91] Fix an intermittent pr_emerg warning about lo becoming free. It looks like this: Message from syslogd@flamingo at Apr 26 00:45:00 ... kernel:unregister_netdevice: waiting for lo to become free. Usage count = 4 They seem to coincide with net namespace teardown. The message is emitted by netdev_wait_allrefs(). Forced a kdump in netdev_run_todo, but found that the refcount on the lo device was already 0 at the time we got to the panic. Used bcc to check the blocking in netdev_run_todo. The only places where we're off cpu there are in the rcu_barrier() and msleep() calls. That behavior is expected. The msleep time coincides with the amount of time we spend waiting for the refcount to reach zero; the rcu_barrier() wait times are not excessive. After looking through the list of callbacks that the netdevice notifiers invoke in this path, it appears that the dst_dev_event is the most interesting. The dst_ifdown path places a hold on the loopback_dev as part of releasing the dev associated with the original dst cache entry. Most of our notifier callbacks are straight-forward, but this one a) looks complex, and b) places a hold on the network interface in question. I constructed a new bcc script that watches various events in the liftime of a dst cache entry. Note that dst_ifdown will take a hold on the loopback device until the invalidated dst entry gets freed. [ __dst_free] on DST: ffff883ccabb7900 IF tap1008300eth0 invoked at 1282115677036183 __dst_free rcu_nocb_kthread kthread ret_from_fork Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dst.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/net/core/dst.c b/net/core/dst.c index 6192f11beec9..13ba4a090c41 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -469,6 +469,20 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, spin_lock_bh(&dst_garbage.lock); dst = dst_garbage.list; dst_garbage.list = NULL; + /* The code in dst_ifdown places a hold on the loopback device. + * If the gc entry processing is set to expire after a lengthy + * interval, this hold can cause netdev_wait_allrefs() to hang + * out and wait for a long time -- until the the loopback + * interface is released. If we're really unlucky, it'll emit + * pr_emerg messages to console too. Reset the interval here, + * so dst cleanups occur in a more timely fashion. + */ + if (dst_garbage.timer_inc > DST_GC_INC) { + dst_garbage.timer_inc = DST_GC_INC; + dst_garbage.timer_expires = DST_GC_MIN; + mod_delayed_work(system_wq, &dst_gc_work, + dst_garbage.timer_expires); + } spin_unlock_bh(&dst_garbage.lock); if (last) From fd6720aefde06eacf17404eed2cad65c6ec103e1 Mon Sep 17 00:00:00 2001 From: Mario Molitor Date: Thu, 8 Jun 2017 22:41:02 +0200 Subject: [PATCH 39/91] stmmac: fix ptp header for GMAC3 hw timestamp According the CYCLON V documention only the bit 16 of snaptypesel should set. (more information see Table 17-20 (cv_5v4.pdf) : Timestamp Snapshot Dependency on Register Bits) Fixes: d2042052a0aa ("stmmac: update the PTP header file") Signed-off-by: Mario Molitor Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 15 ++++++++++++--- drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h | 3 ++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 12236daf7bb6..d54e5d74b3fd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -546,7 +546,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) /* PTP v1, UDP, any kind of event packet */ config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; /* take time stamp for all event messages */ - snap_type_sel = PTP_TCR_SNAPTYPSEL_1; + if (priv->plat->has_gmac4) + snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1; + else + snap_type_sel = PTP_TCR_SNAPTYPSEL_1; ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; @@ -578,7 +581,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; ptp_v2 = PTP_TCR_TSVER2ENA; /* take time stamp for all event messages */ - snap_type_sel = PTP_TCR_SNAPTYPSEL_1; + if (priv->plat->has_gmac4) + snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1; + else + snap_type_sel = PTP_TCR_SNAPTYPSEL_1; ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; @@ -612,7 +618,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; ptp_v2 = PTP_TCR_TSVER2ENA; /* take time stamp for all event messages */ - snap_type_sel = PTP_TCR_SNAPTYPSEL_1; + if (priv->plat->has_gmac4) + snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1; + else + snap_type_sel = PTP_TCR_SNAPTYPSEL_1; ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h index 48fb72fc423c..f4b31d69f60e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h @@ -59,7 +59,8 @@ /* Enable Snapshot for Messages Relevant to Master */ #define PTP_TCR_TSMSTRENA BIT(15) /* Select PTP packets for Taking Snapshots */ -#define PTP_TCR_SNAPTYPSEL_1 GENMASK(17, 16) +#define PTP_TCR_SNAPTYPSEL_1 BIT(16) +#define PTP_GMAC4_TCR_SNAPTYPSEL_1 GENMASK(17, 16) /* Enable MAC address for PTP Frame Filtering */ #define PTP_TCR_TSENMACADDR BIT(18) From 33d4c4821323729b463e45d0b2d32f6a87dcba5b Mon Sep 17 00:00:00 2001 From: Mario Molitor Date: Thu, 8 Jun 2017 23:03:09 +0200 Subject: [PATCH 40/91] stmmac: fix for hw timestamp of GMAC3 unit 1.) Bugfix of function stmmac_get_tx_hwtstamp. Corrected the tx timestamp available check (same as 4.8 and older) Change printout from info syslevel to debug. 2.) Bugfix of function stmmac_get_rx_hwtstamp. Corrected the rx timestamp available check (same as 4.8 and older) Change printout from info syslevel to debug. Fixes: ba1ffd74df74 ("stmmac: fix PTP support for GMAC4") Signed-off-by: Mario Molitor Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 11 +++++++---- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 10 +++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c index aa6476439aee..e0ef02f9503b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c @@ -214,13 +214,13 @@ static int dwmac4_wrback_get_tx_timestamp_status(struct dma_desc *p) { /* Context type from W/B descriptor must be zero */ if (le32_to_cpu(p->des3) & TDES3_CONTEXT_TYPE) - return -EINVAL; + return 0; /* Tx Timestamp Status is 1 so des0 and des1'll have valid values */ if (le32_to_cpu(p->des3) & TDES3_TIMESTAMP_STATUS) - return 0; + return 1; - return 1; + return 0; } static inline u64 dwmac4_get_timestamp(void *desc, u32 ats) @@ -282,7 +282,10 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, u32 ats) } } exit: - return ret; + if (likely(ret == 0)) + return 1; + + return 0; } static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index d54e5d74b3fd..d16d11bfc046 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -434,14 +434,14 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, return; /* check tx tstamp status */ - if (!priv->hw->desc->get_tx_timestamp_status(p)) { + if (priv->hw->desc->get_tx_timestamp_status(p)) { /* get the valid tstamp */ ns = priv->hw->desc->get_timestamp(p, priv->adv_ts); memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); shhwtstamp.hwtstamp = ns_to_ktime(ns); - netdev_info(priv->dev, "get valid TX hw timestamp %llu\n", ns); + netdev_dbg(priv->dev, "get valid TX hw timestamp %llu\n", ns); /* pass tstamp to stack */ skb_tstamp_tx(skb, &shhwtstamp); } @@ -468,19 +468,19 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, return; /* Check if timestamp is available */ - if (!priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) { + if (priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) { /* For GMAC4, the valid timestamp is from CTX next desc. */ if (priv->plat->has_gmac4) ns = priv->hw->desc->get_timestamp(np, priv->adv_ts); else ns = priv->hw->desc->get_timestamp(p, priv->adv_ts); - netdev_info(priv->dev, "get valid RX hw timestamp %llu\n", ns); + netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns); shhwtstamp = skb_hwtstamps(skb); memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); shhwtstamp->hwtstamp = ns_to_ktime(ns); } else { - netdev_err(priv->dev, "cannot get RX hw timestamp\n"); + netdev_dbg(priv->dev, "cannot get RX hw timestamp\n"); } } From 773fc8f6e8d63ec9d840588e161cbb73a01cfc45 Mon Sep 17 00:00:00 2001 From: "ashwanth@codeaurora.org" Date: Fri, 9 Jun 2017 14:24:58 +0530 Subject: [PATCH 41/91] net: rps: send out pending IPI's on CPU hotplug IPI's from the victim cpu are not handled in dev_cpu_callback. So these pending IPI's would be sent to the remote cpu only when NET_RX is scheduled on the victim cpu and since this trigger is unpredictable it would result in packet latencies on the remote cpu. This patch add support to send the pending ipi's of victim cpu. Signed-off-by: Ashwanth Goli Signed-off-by: David S. Miller --- net/core/dev.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 4c15466305c3..54bb8d99d26a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4949,6 +4949,19 @@ __sum16 __skb_gro_checksum_complete(struct sk_buff *skb) } EXPORT_SYMBOL(__skb_gro_checksum_complete); +static void net_rps_send_ipi(struct softnet_data *remsd) +{ +#ifdef CONFIG_RPS + while (remsd) { + struct softnet_data *next = remsd->rps_ipi_next; + + if (cpu_online(remsd->cpu)) + smp_call_function_single_async(remsd->cpu, &remsd->csd); + remsd = next; + } +#endif +} + /* * net_rps_action_and_irq_enable sends any pending IPI's for rps. * Note: called with local irq disabled, but exits with local irq enabled. @@ -4964,14 +4977,7 @@ static void net_rps_action_and_irq_enable(struct softnet_data *sd) local_irq_enable(); /* Send pending IPI's to kick RPS processing on remote cpus. */ - while (remsd) { - struct softnet_data *next = remsd->rps_ipi_next; - - if (cpu_online(remsd->cpu)) - smp_call_function_single_async(remsd->cpu, - &remsd->csd); - remsd = next; - } + net_rps_send_ipi(remsd); } else #endif local_irq_enable(); @@ -8197,7 +8203,7 @@ static int dev_cpu_dead(unsigned int oldcpu) struct sk_buff **list_skb; struct sk_buff *skb; unsigned int cpu; - struct softnet_data *sd, *oldsd; + struct softnet_data *sd, *oldsd, *remsd; local_irq_disable(); cpu = smp_processor_id(); @@ -8238,6 +8244,13 @@ static int dev_cpu_dead(unsigned int oldcpu) raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_enable(); +#ifdef CONFIG_RPS + remsd = oldsd->rps_ipi_list; + oldsd->rps_ipi_list = NULL; +#endif + /* send out pending IPI's on offline CPU */ + net_rps_send_ipi(remsd); + /* Process offline CPU's input_pkt_queue */ while ((skb = __skb_dequeue(&oldsd->process_queue))) { netif_rx_ni(skb); From c7a61cba71fd151cc7d9ebe53a090e0e61eeebf3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 9 Jun 2017 21:33:09 +0200 Subject: [PATCH 42/91] mac80211: free netdev on dev_alloc_name() error The change to remove free_netdev() from ieee80211_if_free() erroneously didn't add the necessary free_netdev() for when ieee80211_if_free() is called directly in one place, rather than as the priv_destructor. Add the missing call. Fixes: cf124db566e6 ("net: Fix inconsistent teardown and release of private netdev state.") Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- net/mac80211/iface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 915d7e1b4545..f5f50150ba1c 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1816,6 +1816,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, ret = dev_alloc_name(ndev, ndev->name); if (ret < 0) { ieee80211_if_free(ndev); + free_netdev(ndev); return ret; } From 92f85f05caa51d844af6ea14ffbc7a786446a644 Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Fri, 9 Jun 2017 17:17:01 +0300 Subject: [PATCH 43/91] bnx2x: Allow vfs to disable txvlan offload VF clients are configured as enforced, meaning firmware is validating the correctness of their ethertype/vid during transmission. Once txvlan is disabled, VF would start getting SKBs for transmission here vlan is on the payload - but it'll pass the packet's ethertype instead of the vid, leading to firmware declaring it as malicious. Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 5f49334dcad5..f619c4cac51f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -3883,15 +3883,26 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) /* when transmitting in a vf, start bd must hold the ethertype * for fw to enforce it */ + u16 vlan_tci = 0; #ifndef BNX2X_STOP_ON_ERROR - if (IS_VF(bp)) + if (IS_VF(bp)) { #endif - tx_start_bd->vlan_or_ethertype = - cpu_to_le16(ntohs(eth->h_proto)); + /* Still need to consider inband vlan for enforced */ + if (__vlan_get_tag(skb, &vlan_tci)) { + tx_start_bd->vlan_or_ethertype = + cpu_to_le16(ntohs(eth->h_proto)); + } else { + tx_start_bd->bd_flags.as_bitfield |= + (X_ETH_INBAND_VLAN << + ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT); + tx_start_bd->vlan_or_ethertype = + cpu_to_le16(vlan_tci); + } #ifndef BNX2X_STOP_ON_ERROR - else + } else { /* used by FW for packet accounting */ tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod); + } #endif } From 3523882229b903e967de05665b871dab87c5df0f Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Fri, 9 Jun 2017 17:17:02 +0300 Subject: [PATCH 44/91] bnx2x: Don't post statistics to malicious VFs Once firmware indicates that a given VF is malicious and until that VF passes an FLR all bets are off - PF can't know anything is happening to the VF [since VF can't communicate anything to its PF]. But PF is currently still periodically asking device to collect statistics for the VF which might in turn fill logs by IOMMU blocking memory access done by the VF's PCI function [in the case VF has unmapped its buffers]. Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 13 ++++++++++++- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 870ea001a720..9ca994d0bab6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -901,6 +901,8 @@ static void bnx2x_vf_flr(struct bnx2x *bp, struct bnx2x_virtf *vf) /* release VF resources */ bnx2x_vf_free_resc(bp, vf); + vf->malicious = false; + /* re-open the mailbox */ bnx2x_vf_enable_mbx(bp, vf->abs_vfid); return; @@ -1822,9 +1824,11 @@ int bnx2x_iov_eq_sp_event(struct bnx2x *bp, union event_ring_elem *elem) vf->abs_vfid, qidx); bnx2x_vf_handle_rss_update_eqe(bp, vf); case EVENT_RING_OPCODE_VF_FLR: - case EVENT_RING_OPCODE_MALICIOUS_VF: /* Do nothing for now */ return 0; + case EVENT_RING_OPCODE_MALICIOUS_VF: + vf->malicious = true; + return 0; } return 0; @@ -1905,6 +1909,13 @@ void bnx2x_iov_adjust_stats_req(struct bnx2x *bp) continue; } + if (vf->malicious) { + DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_STATS), + "vf %d malicious so no stats for it\n", + vf->abs_vfid); + continue; + } + DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_STATS), "add addresses for vf %d\n", vf->abs_vfid); for_each_vfq(vf, j) { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 888d0b6632e8..53466f6cebab 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -141,6 +141,7 @@ struct bnx2x_virtf { #define VF_RESET 3 /* VF FLR'd, pending cleanup */ bool flr_clnup_stage; /* true during flr cleanup */ + bool malicious; /* true if FW indicated so, until FLR */ /* dma */ dma_addr_t fw_stat_map; From d8dba51de5dfb55225b169653bbd7379ac0d0c63 Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Fri, 9 Jun 2017 23:50:57 +0200 Subject: [PATCH 45/91] net: aquantia: atlantic: remove declaration of hw_atl_utils_hw_set_power This function is not defined, so no need to declare it. As I don't have the hardware, I'd be very pleased if someone may test this patch. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h index b8e3d88f0879..a66aee51ab5b 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h @@ -193,9 +193,6 @@ int hw_atl_utils_hw_get_regs(struct aq_hw_s *self, struct aq_hw_caps_s *aq_hw_caps, u32 *regs_buff); -int hw_atl_utils_hw_get_settings(struct aq_hw_s *self, - struct ethtool_cmd *cmd); - int hw_atl_utils_hw_set_power(struct aq_hw_s *self, unsigned int power_state); From 9b3dc0a17d7388c4fb83736ca45253a93e994ce4 Mon Sep 17 00:00:00 2001 From: Dominik Heidler Date: Fri, 9 Jun 2017 16:29:47 +0200 Subject: [PATCH 46/91] l2tp: cast l2tp traffic counter to unsigned This fixes a counter problem on 32bit systems: When the rx_bytes counter reached 2 GiB, it jumpd to (2^64 Bytes - 2GiB) Bytes. rtnl_link_stats64 has __u64 type and atomic_long_read returns atomic_long_t which is signed. Due to the conversation we get an incorrect value on 32bit systems if the MSB of the atomic_long_t value is set. CC: Tom Parkin Fixes: 7b7c0719cd7a ("l2tp: avoid deadlock in l2tp stats update") Signed-off-by: Dominik Heidler Signed-off-by: David S. Miller --- net/l2tp/l2tp_eth.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index f7c54ece3733..4de2ec94b08c 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -114,12 +114,13 @@ static void l2tp_eth_get_stats64(struct net_device *dev, { struct l2tp_eth *priv = netdev_priv(dev); - stats->tx_bytes = atomic_long_read(&priv->tx_bytes); - stats->tx_packets = atomic_long_read(&priv->tx_packets); - stats->tx_dropped = atomic_long_read(&priv->tx_dropped); - stats->rx_bytes = atomic_long_read(&priv->rx_bytes); - stats->rx_packets = atomic_long_read(&priv->rx_packets); - stats->rx_errors = atomic_long_read(&priv->rx_errors); + stats->tx_bytes = (unsigned long) atomic_long_read(&priv->tx_bytes); + stats->tx_packets = (unsigned long) atomic_long_read(&priv->tx_packets); + stats->tx_dropped = (unsigned long) atomic_long_read(&priv->tx_dropped); + stats->rx_bytes = (unsigned long) atomic_long_read(&priv->rx_bytes); + stats->rx_packets = (unsigned long) atomic_long_read(&priv->rx_packets); + stats->rx_errors = (unsigned long) atomic_long_read(&priv->rx_errors); + } static const struct net_device_ops l2tp_eth_netdev_ops = { From bf292f1b2c813f1d6ac49b04bd1a9863d8314266 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 9 Jun 2017 22:37:22 -0300 Subject: [PATCH 47/91] net: fec: Add a fec_enet_clear_ethtool_stats() stub for CONFIG_M5272 Commit 2b30842b23b9 ("net: fec: Clear and enable MIB counters on imx51") introduced fec_enet_clear_ethtool_stats(), but missed to add a stub for the CONFIG_M5272=y case, causing build failure for the m5272c3_defconfig. Add the missing empty stub to fix the build failure. Reported-by: Paul Gortmaker Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index f7c8649fd28f..2205e5b32a10 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2361,6 +2361,10 @@ static int fec_enet_get_sset_count(struct net_device *dev, int sset) static inline void fec_enet_update_ethtool_stats(struct net_device *dev) { } + +static inline void fec_enet_clear_ethtool_stats(struct net_device *dev) +{ +} #endif /* !defined(CONFIG_M5272) */ /* ITR clock source is enet system clock (clk_ahb). From 581409dacc9176b0de1f6c4ca8d66e13aa8e1b29 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Sat, 10 Jun 2017 14:48:14 +0800 Subject: [PATCH 48/91] sctp: disable BH in sctp_for_each_endpoint Now sctp holds read_lock when foreach sctp_ep_hashtable without disabling BH. If CPU schedules to another thread A at this moment, the thread A may be trying to hold the write_lock with disabling BH. As BH is disabled and CPU cannot schedule back to the thread holding the read_lock, while the thread A keeps waiting for the read_lock. A dead lock would be triggered by this. This patch is to fix this dead lock by calling read_lock_bh instead to disable BH when holding the read_lock in sctp_for_each_endpoint. Fixes: 626d16f50f39 ("sctp: export some apis or variables for sctp_diag and reuse some for proc") Reported-by: Xiumei Mu Signed-off-by: Xin Long Acked-by: Marcelo Ricardo Leitner Signed-off-by: David S. Miller --- net/sctp/socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f16c8d97b7f3..30aa0a529215 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4622,13 +4622,13 @@ int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), for (head = sctp_ep_hashtable; hash < sctp_ep_hashsize; hash++, head++) { - read_lock(&head->lock); + read_lock_bh(&head->lock); sctp_for_each_hentry(epb, &head->chain) { err = cb(sctp_ep(epb), p); if (err) break; } - read_unlock(&head->lock); + read_unlock_bh(&head->lock); } return err; From 5aa32f53ab93175442dffbd95a231d0798cab4d1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 10 Jun 2017 16:44:28 -0400 Subject: [PATCH 49/91] Revert "net: fec: Add a fec_enet_clear_ethtool_stats() stub for CONFIG_M5272" This reverts commit bf292f1b2c813f1d6ac49b04bd1a9863d8314266. It belongs in 'net-next' not 'net'. Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 2205e5b32a10..f7c8649fd28f 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2361,10 +2361,6 @@ static int fec_enet_get_sset_count(struct net_device *dev, int sset) static inline void fec_enet_update_ethtool_stats(struct net_device *dev) { } - -static inline void fec_enet_clear_ethtool_stats(struct net_device *dev) -{ -} #endif /* !defined(CONFIG_M5272) */ /* ITR clock source is enet system clock (clk_ahb). From f146e872eb12ebbe92d8e583b2637e0741440db3 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Sat, 10 Jun 2017 16:49:39 +0800 Subject: [PATCH 50/91] net: caif: Fix a sleep-in-atomic bug in cfpkt_create_pfx The kernel may sleep under a rcu read lock in cfpkt_create_pfx, and the function call path is: cfcnfg_linkup_rsp (acquire the lock by rcu_read_lock) cfctrl_linkdown_req cfpkt_create cfpkt_create_pfx alloc_skb(GFP_KERNEL) --> may sleep cfserl_receive (acquire the lock by rcu_read_lock) cfpkt_split cfpkt_create_pfx alloc_skb(GFP_KERNEL) --> may sleep There is "in_interrupt" in cfpkt_create_pfx to decide use "GFP_KERNEL" or "GFP_ATOMIC". In this situation, "GFP_KERNEL" is used because the function is called under a rcu read lock, instead in interrupt. To fix it, only "GFP_ATOMIC" is used in cfpkt_create_pfx. Signed-off-by: Jia-Ju Bai Signed-off-by: David S. Miller --- net/caif/cfpkt_skbuff.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c index 59ce1fcc220c..71b6ab240dea 100644 --- a/net/caif/cfpkt_skbuff.c +++ b/net/caif/cfpkt_skbuff.c @@ -81,11 +81,7 @@ static struct cfpkt *cfpkt_create_pfx(u16 len, u16 pfx) { struct sk_buff *skb; - if (likely(in_interrupt())) - skb = alloc_skb(len + pfx, GFP_ATOMIC); - else - skb = alloc_skb(len + pfx, GFP_KERNEL); - + skb = alloc_skb(len + pfx, GFP_ATOMIC); if (unlikely(skb == NULL)) return NULL; From 343eba69c6968190d8654b857aea952fed9a6749 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Sat, 10 Jun 2017 17:03:35 +0800 Subject: [PATCH 51/91] net: tipc: Fix a sleep-in-atomic bug in tipc_msg_reverse The kernel may sleep under a rcu read lock in tipc_msg_reverse, and the function call path is: tipc_l2_rcv_msg (acquire the lock by rcu_read_lock) tipc_rcv tipc_sk_rcv tipc_msg_reverse pskb_expand_head(GFP_KERNEL) --> may sleep tipc_node_broadcast tipc_node_xmit_skb tipc_node_xmit tipc_sk_rcv tipc_msg_reverse pskb_expand_head(GFP_KERNEL) --> may sleep To fix it, "GFP_KERNEL" is replaced with "GFP_ATOMIC". Signed-off-by: Jia-Ju Bai Signed-off-by: David S. Miller --- net/tipc/msg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 312ef7de57d7..ab3087687a32 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -508,7 +508,7 @@ bool tipc_msg_reverse(u32 own_node, struct sk_buff **skb, int err) } if (skb_cloned(_skb) && - pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_KERNEL)) + pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_ATOMIC)) goto exit; /* Now reverse the concerned fields */ From 56b8aae959499508090b2d2db6961ed905f38164 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Sat, 10 Jun 2017 23:18:21 +0200 Subject: [PATCH 52/91] net: mvpp2: remove mvpp2_bm_cookie_{build,pool_get} This commit removes the useless remove mvpp2_bm_cookie_{build,pool_get} functions. All what mvpp2_bm_cookie_build() was doing is compute a 32-bit value by concatenating the pool number and the CPU number... only to get the pool number re-extracted by mvpp2_bm_cookie_pool_get() later on. Instead, just get the pool number directly from RX descriptor status, and pass it to mvpp2_pool_refill() and mvpp2_rx_refill(). This has the added benefit of dropping a smp_processor_id() call in a migration-enabled context, which is wrong, and is the original motivation for making this change. Fixes: 3f518509dedc9 ("ethernet: Add new driver for Marvell Armada 375 network unit") Signed-off-by: Thomas Petazzoni Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2.c | 47 +++++++++------------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index 70bca2a6fb02..5841e53614c6 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -3920,12 +3920,6 @@ static inline u32 mvpp2_bm_cookie_pool_set(u32 cookie, int pool) return bm; } -/* Get pool number from a BM cookie */ -static inline int mvpp2_bm_cookie_pool_get(unsigned long cookie) -{ - return (cookie >> MVPP2_BM_COOKIE_POOL_OFFS) & 0xFF; -} - /* Release buffer to BM */ static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool, dma_addr_t buf_dma_addr, @@ -3961,12 +3955,10 @@ static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool, } /* Refill BM pool */ -static void mvpp2_pool_refill(struct mvpp2_port *port, u32 bm, +static void mvpp2_pool_refill(struct mvpp2_port *port, int pool, dma_addr_t dma_addr, phys_addr_t phys_addr) { - int pool = mvpp2_bm_cookie_pool_get(bm); - mvpp2_bm_pool_put(port, pool, dma_addr, phys_addr); } @@ -4513,21 +4505,6 @@ static void mvpp2_rxq_offset_set(struct mvpp2_port *port, mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val); } -/* Obtain BM cookie information from descriptor */ -static u32 mvpp2_bm_cookie_build(struct mvpp2_port *port, - struct mvpp2_rx_desc *rx_desc) -{ - int cpu = smp_processor_id(); - int pool; - - pool = (mvpp2_rxdesc_status_get(port, rx_desc) & - MVPP2_RXD_BM_POOL_ID_MASK) >> - MVPP2_RXD_BM_POOL_ID_OFFS; - - return ((pool & 0xFF) << MVPP2_BM_COOKIE_POOL_OFFS) | - ((cpu & 0xFF) << MVPP2_BM_COOKIE_CPU_OFFS); -} - /* Tx descriptors helper methods */ /* Get pointer to next Tx descriptor to be processed (send) by HW */ @@ -4978,9 +4955,13 @@ static void mvpp2_rxq_drop_pkts(struct mvpp2_port *port, for (i = 0; i < rx_received; i++) { struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq); - u32 bm = mvpp2_bm_cookie_build(port, rx_desc); + u32 status = mvpp2_rxdesc_status_get(port, rx_desc); + int pool; - mvpp2_pool_refill(port, bm, + pool = (status & MVPP2_RXD_BM_POOL_ID_MASK) >> + MVPP2_RXD_BM_POOL_ID_OFFS; + + mvpp2_pool_refill(port, pool, mvpp2_rxdesc_dma_addr_get(port, rx_desc), mvpp2_rxdesc_cookie_get(port, rx_desc)); } @@ -5418,7 +5399,7 @@ static void mvpp2_rx_csum(struct mvpp2_port *port, u32 status, /* Reuse skb if possible, or allocate a new skb and add it to BM pool */ static int mvpp2_rx_refill(struct mvpp2_port *port, - struct mvpp2_bm_pool *bm_pool, u32 bm) + struct mvpp2_bm_pool *bm_pool, int pool) { dma_addr_t dma_addr; phys_addr_t phys_addr; @@ -5430,7 +5411,7 @@ static int mvpp2_rx_refill(struct mvpp2_port *port, if (!buf) return -ENOMEM; - mvpp2_pool_refill(port, bm, dma_addr, phys_addr); + mvpp2_pool_refill(port, pool, dma_addr, phys_addr); return 0; } @@ -5488,7 +5469,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo, unsigned int frag_size; dma_addr_t dma_addr; phys_addr_t phys_addr; - u32 bm, rx_status; + u32 rx_status; int pool, rx_bytes, err; void *data; @@ -5500,8 +5481,8 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo, phys_addr = mvpp2_rxdesc_cookie_get(port, rx_desc); data = (void *)phys_to_virt(phys_addr); - bm = mvpp2_bm_cookie_build(port, rx_desc); - pool = mvpp2_bm_cookie_pool_get(bm); + pool = (rx_status & MVPP2_RXD_BM_POOL_ID_MASK) >> + MVPP2_RXD_BM_POOL_ID_OFFS; bm_pool = &port->priv->bm_pools[pool]; /* In case of an error, release the requested buffer pointer @@ -5514,7 +5495,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo, dev->stats.rx_errors++; mvpp2_rx_error(port, rx_desc); /* Return the buffer to the pool */ - mvpp2_pool_refill(port, bm, dma_addr, phys_addr); + mvpp2_pool_refill(port, pool, dma_addr, phys_addr); continue; } @@ -5529,7 +5510,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo, goto err_drop_frame; } - err = mvpp2_rx_refill(port, bm_pool, bm); + err = mvpp2_rx_refill(port, bm_pool, pool); if (err) { netdev_err(port->dev, "failed to refill BM pools\n"); goto err_drop_frame; From a704bb5c052bbd6b77c6530a2e83cef42486e335 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Sat, 10 Jun 2017 23:18:22 +0200 Subject: [PATCH 53/91] net: mvpp2: use {get, put}_cpu() instead of smp_processor_id() smp_processor_id() should not be used in migration-enabled contexts. We originally thought it was OK in the specific situation of this driver, but it was wrong, and calling smp_processor_id() in a migration-enabled context prints a big fat warning when CONFIG_DEBUG_PREEMPT=y. Therefore, this commit replaces the smp_processor_id() in migration-enabled contexts by the appropriate get_cpu/put_cpu sections. Reported-by: Marc Zyngier Fixes: a786841df72e ("net: mvpp2: handle register mapping and access for PPv2.2") Signed-off-by: Thomas Petazzoni Tested-by: Marc Zyngier Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index 5841e53614c6..33c901622ed5 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -3719,7 +3719,7 @@ static void mvpp2_bm_bufs_get_addrs(struct device *dev, struct mvpp2 *priv, dma_addr_t *dma_addr, phys_addr_t *phys_addr) { - int cpu = smp_processor_id(); + int cpu = get_cpu(); *dma_addr = mvpp2_percpu_read(priv, cpu, MVPP2_BM_PHY_ALLOC_REG(bm_pool->id)); @@ -3740,6 +3740,8 @@ static void mvpp2_bm_bufs_get_addrs(struct device *dev, struct mvpp2 *priv, if (sizeof(phys_addr_t) == 8) *phys_addr |= (u64)phys_addr_highbits << 32; } + + put_cpu(); } /* Free all buffers from the pool */ @@ -3925,7 +3927,7 @@ static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool, dma_addr_t buf_dma_addr, phys_addr_t buf_phys_addr) { - int cpu = smp_processor_id(); + int cpu = get_cpu(); if (port->priv->hw_version == MVPP22) { u32 val = 0; @@ -3952,6 +3954,8 @@ static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool, MVPP2_BM_VIRT_RLS_REG, buf_phys_addr); mvpp2_percpu_write(port->priv, cpu, MVPP2_BM_PHY_RLS_REG(pool), buf_dma_addr); + + put_cpu(); } /* Refill BM pool */ @@ -4732,7 +4736,7 @@ static void mvpp2_txp_max_tx_size_set(struct mvpp2_port *port) static void mvpp2_rx_pkts_coal_set(struct mvpp2_port *port, struct mvpp2_rx_queue *rxq) { - int cpu = smp_processor_id(); + int cpu = get_cpu(); if (rxq->pkts_coal > MVPP2_OCCUPIED_THRESH_MASK) rxq->pkts_coal = MVPP2_OCCUPIED_THRESH_MASK; @@ -4740,6 +4744,8 @@ static void mvpp2_rx_pkts_coal_set(struct mvpp2_port *port, mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_NUM_REG, rxq->id); mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_THRESH_REG, rxq->pkts_coal); + + put_cpu(); } static u32 mvpp2_usec_to_cycles(u32 usec, unsigned long clk_hz) @@ -4920,7 +4926,7 @@ static int mvpp2_rxq_init(struct mvpp2_port *port, mvpp2_write(port->priv, MVPP2_RXQ_STATUS_REG(rxq->id), 0); /* Set Rx descriptors queue starting address - indirect access */ - cpu = smp_processor_id(); + cpu = get_cpu(); mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_NUM_REG, rxq->id); if (port->priv->hw_version == MVPP21) rxq_dma = rxq->descs_dma; @@ -4929,6 +4935,7 @@ static int mvpp2_rxq_init(struct mvpp2_port *port, mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_ADDR_REG, rxq_dma); mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_SIZE_REG, rxq->size); mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_INDEX_REG, 0); + put_cpu(); /* Set Offset */ mvpp2_rxq_offset_set(port, rxq->id, NET_SKB_PAD); @@ -4991,10 +4998,11 @@ static void mvpp2_rxq_deinit(struct mvpp2_port *port, * free descriptor number */ mvpp2_write(port->priv, MVPP2_RXQ_STATUS_REG(rxq->id), 0); - cpu = smp_processor_id(); + cpu = get_cpu(); mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_NUM_REG, rxq->id); mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_ADDR_REG, 0); mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_SIZE_REG, 0); + put_cpu(); } /* Create and initialize a Tx queue */ @@ -5017,7 +5025,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port, txq->last_desc = txq->size - 1; /* Set Tx descriptors queue starting address - indirect access */ - cpu = smp_processor_id(); + cpu = get_cpu(); mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_NUM_REG, txq->id); mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_DESC_ADDR_REG, txq->descs_dma); @@ -5042,6 +5050,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port, mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_PREF_BUF_REG, MVPP2_PREF_BUF_PTR(desc) | MVPP2_PREF_BUF_SIZE_16 | MVPP2_PREF_BUF_THRESH(desc_per_txq / 2)); + put_cpu(); /* WRR / EJP configuration - indirect access */ tx_port_num = mvpp2_egress_port(port); @@ -5112,10 +5121,11 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port, mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->id), 0); /* Set Tx descriptors queue starting address and size */ - cpu = smp_processor_id(); + cpu = get_cpu(); mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_NUM_REG, txq->id); mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_DESC_ADDR_REG, 0); mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_DESC_SIZE_REG, 0); + put_cpu(); } /* Cleanup Tx ports */ @@ -5125,7 +5135,7 @@ static void mvpp2_txq_clean(struct mvpp2_port *port, struct mvpp2_tx_queue *txq) int delay, pending, cpu; u32 val; - cpu = smp_processor_id(); + cpu = get_cpu(); mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_NUM_REG, txq->id); val = mvpp2_percpu_read(port->priv, cpu, MVPP2_TXQ_PREF_BUF_REG); val |= MVPP2_TXQ_DRAIN_EN_MASK; @@ -5152,6 +5162,7 @@ static void mvpp2_txq_clean(struct mvpp2_port *port, struct mvpp2_tx_queue *txq) val &= ~MVPP2_TXQ_DRAIN_EN_MASK; mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_PREF_BUF_REG, val); + put_cpu(); for_each_present_cpu(cpu) { txq_pcpu = per_cpu_ptr(txq->pcpu, cpu); From 57f35c93a2072c1f66ab1728a77a9ee4bc33bf42 Mon Sep 17 00:00:00 2001 From: Mohamad Haj Yahia Date: Thu, 25 May 2017 16:46:14 +0300 Subject: [PATCH 54/91] net/mlx5: Fix create vport flow table flow Send vport number to the create flow table inner method instead of ignoring the vport argument and sending always 0. Fixes: b3ba51498bdd ('net/mlx5: Refactor create flow table method to accept underlay QP') Signed-off-by: Mohamad Haj Yahia Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 0e487e8ca634..8f5125ccd8d4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -862,7 +862,7 @@ struct mlx5_flow_table *mlx5_create_vport_flow_table(struct mlx5_flow_namespace ft_attr.level = level; ft_attr.prio = prio; - return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_NORMAL, 0); + return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_NORMAL, vport); } struct mlx5_flow_table* From 3fece5d676939f42f434c63dfe1bd42d7d94e6f0 Mon Sep 17 00:00:00 2001 From: Mohamad Haj Yahia Date: Sun, 9 Apr 2017 17:19:37 +0300 Subject: [PATCH 55/91] net/mlx5: Continue health polling until it is explicitly stopped The issue is that when we get an assert we will stop polling the health and thus we cant enter error state when we have a real health issue. Fixes: fd76ee4da55a ('net/mlx5_core: Fix internal error detection conditions') Signed-off-by: Mohamad Haj Yahia Reviewed-by: Daniel Jurgens Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/health.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 44f59b1d6f0f..f27f84ffbc85 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -275,10 +275,8 @@ static void poll_health(unsigned long data) struct mlx5_core_health *health = &dev->priv.health; u32 count; - if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { - mod_timer(&health->timer, get_next_poll_jiffies()); - return; - } + if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) + goto out; count = ioread32be(health->health_counter); if (count == health->prev) @@ -290,8 +288,6 @@ static void poll_health(unsigned long data) if (health->miss_counter == MAX_MISSES) { dev_err(&dev->pdev->dev, "device's health compromised - reached miss count\n"); print_health_info(dev); - } else { - mod_timer(&health->timer, get_next_poll_jiffies()); } if (in_fatal(dev) && !health->sick) { @@ -305,6 +301,9 @@ static void poll_health(unsigned long data) "new health works are not permitted at this stage\n"); spin_unlock(&health->wq_lock); } + +out: + mod_timer(&health->timer, get_next_poll_jiffies()); } void mlx5_start_health_poll(struct mlx5_core_dev *dev) From f729860a177d097ac44321fb2f7d927a0c54c5a3 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Mon, 8 May 2017 11:46:50 -0500 Subject: [PATCH 56/91] net/mlx5: Remove several module events out of ethtool stats Remove the following module event counters out of ethtool stats. The reason for removing these event counters is that these events do not occur without techinician's intervention. module_pwr_budget_exd module_long_range module_no_eeprom module_enforce_part module_unknown_id module_unknown_status module_plug Fixes: bedb7c909c19 ("net/mlx5e: Add port module event counters to ethtool stats") Signed-off-by: Huy Nguyen Reviewed by: Gal Pressman Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_stats.h | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 53e4992d6511..f81c3aa60b46 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -417,20 +417,13 @@ struct mlx5e_stats { }; static const struct counter_desc mlx5e_pme_status_desc[] = { - { "module_plug", 0 }, { "module_unplug", 8 }, }; static const struct counter_desc mlx5e_pme_error_desc[] = { - { "module_pwr_budget_exd", 0 }, /* power budget exceed */ - { "module_long_range", 8 }, /* long range for non MLNX cable */ - { "module_bus_stuck", 16 }, /* bus stuck (I2C or data shorted) */ - { "module_no_eeprom", 24 }, /* no eeprom/retry time out */ - { "module_enforce_part", 32 }, /* enforce part number list */ - { "module_unknown_id", 40 }, /* unknown identifier */ - { "module_high_temp", 48 }, /* high temperature */ + { "module_bus_stuck", 16 }, /* bus stuck (I2C or data shorted) */ + { "module_high_temp", 48 }, /* high temperature */ { "module_bad_shorted", 56 }, /* bad or shorted cable/module */ - { "module_unknown_status", 64 }, }; #endif /* __MLX5_EN_STATS_H__ */ From c3164d2fc48fd4fa0477ab658b644559c3fe9073 Mon Sep 17 00:00:00 2001 From: Tal Gilboa Date: Mon, 15 May 2017 14:13:16 +0300 Subject: [PATCH 57/91] net/mlx5e: Added BW check for DIM decision mechanism DIM (Dynamically-tuned Interrupt Moderation) is a mechanism designed for changing the channel interrupt moderation values in order to reduce CPU overhead for all traffic types. Until now only interrupt and packet rate were sampled. We found a scenario on which we get a false indication since a change in DIM caused more aggregation and reduced packet rate while increasing BW. We now regard a change as succesfull iff: current_BW > (prev_BW + threshold) or current_BW ~= prev_BW and current_PR > (prev_PR + threshold) or current_BW ~= prev_BW and current_PR ~= prev_PR and current_IR < (prev_IR - threshold) Where BW = Bandwidth, PR = Packet rate and IR = Interrupt rate Improvements (ConnectX-4Lx 25GbE, single RX queue, LRO off) -------------------------------------------------- packet size | before[Mb/s] | after[Mb/s] | gain | 2B | 343.4 | 359.4 | 4.5% | 16B | 2739.7 | 2814.8 | 2.7% | 64B | 9739 | 10185.3 | 4.5% | Fixes: cb3c7fd4f839 ("net/mlx5e: Support adaptive RX coalescing") Signed-off-by: Tal Gilboa Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 + .../ethernet/mellanox/mlx5/core/en_rx_am.c | 37 ++++++++++--------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 2fd044b23875..429da21a583d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -458,12 +458,14 @@ struct mlx5e_mpw_info { struct mlx5e_rx_am_stats { int ppms; /* packets per msec */ + int bpms; /* bytes per msec */ int epms; /* events per msec */ }; struct mlx5e_rx_am_sample { ktime_t time; unsigned int pkt_ctr; + unsigned int byte_ctr; u16 event_ctr; }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c index 02dd3a95ed8f..54cdda957f9a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c @@ -183,28 +183,27 @@ static void mlx5e_am_exit_parking(struct mlx5e_rx_am *am) mlx5e_am_step(am); } +#define IS_SIGNIFICANT_DIFF(val, ref) \ + (((100 * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */ + static int mlx5e_am_stats_compare(struct mlx5e_rx_am_stats *curr, struct mlx5e_rx_am_stats *prev) { - int diff; - - if (!prev->ppms) - return curr->ppms ? MLX5E_AM_STATS_BETTER : + if (!prev->bpms) + return curr->bpms ? MLX5E_AM_STATS_BETTER : MLX5E_AM_STATS_SAME; - diff = curr->ppms - prev->ppms; - if (((100 * abs(diff)) / prev->ppms) > 10) /* more than 10% diff */ - return (diff > 0) ? MLX5E_AM_STATS_BETTER : - MLX5E_AM_STATS_WORSE; + if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms)) + return (curr->bpms > prev->bpms) ? MLX5E_AM_STATS_BETTER : + MLX5E_AM_STATS_WORSE; - if (!prev->epms) - return curr->epms ? MLX5E_AM_STATS_WORSE : - MLX5E_AM_STATS_SAME; + if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms)) + return (curr->ppms > prev->ppms) ? MLX5E_AM_STATS_BETTER : + MLX5E_AM_STATS_WORSE; - diff = curr->epms - prev->epms; - if (((100 * abs(diff)) / prev->epms) > 10) /* more than 10% diff */ - return (diff < 0) ? MLX5E_AM_STATS_BETTER : - MLX5E_AM_STATS_WORSE; + if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms)) + return (curr->epms < prev->epms) ? MLX5E_AM_STATS_BETTER : + MLX5E_AM_STATS_WORSE; return MLX5E_AM_STATS_SAME; } @@ -266,6 +265,7 @@ static void mlx5e_am_sample(struct mlx5e_rq *rq, { s->time = ktime_get(); s->pkt_ctr = rq->stats.packets; + s->byte_ctr = rq->stats.bytes; s->event_ctr = rq->cq.event_ctr; } @@ -278,12 +278,15 @@ static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start, /* u32 holds up to 71 minutes, should be enough */ u32 delta_us = ktime_us_delta(end->time, start->time); unsigned int npkts = end->pkt_ctr - start->pkt_ctr; + unsigned int nbytes = end->byte_ctr - start->byte_ctr; if (!delta_us) return; - curr_stats->ppms = (npkts * USEC_PER_MSEC) / delta_us; - curr_stats->epms = (MLX5E_AM_NEVENTS * USEC_PER_MSEC) / delta_us; + curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us); + curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us); + curr_stats->epms = DIV_ROUND_UP(MLX5E_AM_NEVENTS * USEC_PER_MSEC, + delta_us); } void mlx5e_rx_am_work(struct work_struct *work) From 53acd76ce571e3b71f9205f2d49ab285a9f1aad8 Mon Sep 17 00:00:00 2001 From: Tal Gilboa Date: Mon, 29 May 2017 17:02:55 +0300 Subject: [PATCH 58/91] net/mlx5e: Fix wrong indications in DIM due to counter wraparound DIM (Dynamically-tuned Interrupt Moderation) is a mechanism designed for changing the channel interrupt moderation values in order to reduce CPU overhead for all traffic types. Each iteration of the algorithm, DIM calculates the difference in throughput, packet rate and interrupt rate from last iteration in order to make a decision. DIM relies on counters for each metric. When these counters get to their type's max value they wraparound. In this case the delta between 'end' and 'start' samples is negative and when translated to unsigned integers - very high. This results in a false indication to the algorithm and might result in a wrong decision. The fix calculates the 'distance' between 'end' and 'start' samples in a cyclic way around the relevant type's max value. It can also be viewed as an absolute value around the type's max value instead of around 0. Testing show higher stability in DIM profile selection and no wraparound issues. Fixes: cb3c7fd4f839 ("net/mlx5e: Support adaptive RX coalescing") Signed-off-by: Tal Gilboa Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 8 ++++---- drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c | 10 +++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 429da21a583d..944fc1742464 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -463,10 +463,10 @@ struct mlx5e_rx_am_stats { }; struct mlx5e_rx_am_sample { - ktime_t time; - unsigned int pkt_ctr; - unsigned int byte_ctr; - u16 event_ctr; + ktime_t time; + u32 pkt_ctr; + u32 byte_ctr; + u16 event_ctr; }; struct mlx5e_rx_am { /* Adaptive Moderation */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c index 54cdda957f9a..acf32fe952cd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c @@ -270,6 +270,8 @@ static void mlx5e_am_sample(struct mlx5e_rq *rq, } #define MLX5E_AM_NEVENTS 64 +#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) +#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1)) static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start, struct mlx5e_rx_am_sample *end, @@ -277,8 +279,9 @@ static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start, { /* u32 holds up to 71 minutes, should be enough */ u32 delta_us = ktime_us_delta(end->time, start->time); - unsigned int npkts = end->pkt_ctr - start->pkt_ctr; - unsigned int nbytes = end->byte_ctr - start->byte_ctr; + u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr); + u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr, + start->byte_ctr); if (!delta_us) return; @@ -311,7 +314,8 @@ void mlx5e_rx_am(struct mlx5e_rq *rq) switch (am->state) { case MLX5E_AM_MEASURE_IN_PROGRESS: - nevents = rq->cq.event_ctr - am->start_sample.event_ctr; + nevents = BIT_GAP(BITS_PER_TYPE(u16), rq->cq.event_ctr, + am->start_sample.event_ctr); if (nevents < MLX5E_AM_NEVENTS) break; mlx5e_am_sample(rq, &end_sample); From 91828bd89940e8145f91751a015bc11bc486aad0 Mon Sep 17 00:00:00 2001 From: Majd Dibbiny Date: Sun, 28 May 2017 14:47:56 +0300 Subject: [PATCH 59/91] net/mlx5: Enable 4K UAR only when page size is bigger than 4K When the page size isn't bigger than 4K, there is no added value of enabling 4K UAR feature in the Firmware. Modified the condition of enabling the 4K UAR accordingly. Fixes: f502d834950a ("net/mlx5: Activate support for 4K UARs") Signed-off-by: Majd Dibbiny Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index af945edfee19..4f577a5abf88 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -537,8 +537,10 @@ static int handle_hca_cap(struct mlx5_core_dev *dev) /* disable cmdif checksum */ MLX5_SET(cmd_hca_cap, set_hca_cap, cmdif_checksum, 0); - /* If the HCA supports 4K UARs use it */ - if (MLX5_CAP_GEN_MAX(dev, uar_4k)) + /* Enable 4K UAR only when HCA supports it and page size is bigger + * than 4K. + */ + if (MLX5_CAP_GEN_MAX(dev, uar_4k) && PAGE_SIZE > 4096) MLX5_SET(cmd_hca_cap, set_hca_cap, uar_4k, 1); MLX5_SET(cmd_hca_cap, set_hca_cap, log_uar_page_sz, PAGE_SHIFT - 12); From a77c1aafcc906f657d1a0890c1d898be9ee1d5c9 Mon Sep 17 00:00:00 2001 From: Netanel Belgazal Date: Sun, 11 Jun 2017 15:42:43 +0300 Subject: [PATCH 60/91] net: ena: fix rare uncompleted admin command false alarm The current flow to detect admin completion is: while (command_not_completed) { if (timeout) error check_for_completion() sleep() } So in case the sleep took more than the timeout (in case the thread/workqueue was not scheduled due to higher priority task or prolonged VMexit), the driver can detect a stall even if the completion is present. The fix changes the order of this function to first check for completion and only after that check if the timeout expired. Fixes: 1738cd3ed342 ("Add a driver for Amazon Elastic Network Adapters (ENA)") Signed-off-by: Netanel Belgazal Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_com.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index 08d11cede9c9..e1c2fab6292f 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -508,15 +508,20 @@ static int ena_com_comp_status_to_errno(u8 comp_status) static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_ctx, struct ena_com_admin_queue *admin_queue) { - unsigned long flags; - u32 start_time; + unsigned long flags, timeout; int ret; - start_time = ((u32)jiffies_to_usecs(jiffies)); + timeout = jiffies + ADMIN_CMD_TIMEOUT_US; - while (comp_ctx->status == ENA_CMD_SUBMITTED) { - if ((((u32)jiffies_to_usecs(jiffies)) - start_time) > - ADMIN_CMD_TIMEOUT_US) { + while (1) { + spin_lock_irqsave(&admin_queue->q_lock, flags); + ena_com_handle_admin_completion(admin_queue); + spin_unlock_irqrestore(&admin_queue->q_lock, flags); + + if (comp_ctx->status != ENA_CMD_SUBMITTED) + break; + + if (time_is_before_jiffies(timeout)) { pr_err("Wait for completion (polling) timeout\n"); /* ENA didn't have any completion */ spin_lock_irqsave(&admin_queue->q_lock, flags); @@ -528,10 +533,6 @@ static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_c goto err; } - spin_lock_irqsave(&admin_queue->q_lock, flags); - ena_com_handle_admin_completion(admin_queue); - spin_unlock_irqrestore(&admin_queue->q_lock, flags); - msleep(100); } From 418df30f7e9e8f4795fb2f3abf9744e5886df5ca Mon Sep 17 00:00:00 2001 From: Netanel Belgazal Date: Sun, 11 Jun 2017 15:42:44 +0300 Subject: [PATCH 61/91] net: ena: fix bug that might cause hang after consecutive open/close interface. Fixing a bug that the driver does not unmask the IO interrupts in ndo_open(): occasionally, the MSI-X interrupt (for one or more IO queues) can be masked when ndo_close() was called. If that is followed by ndo open(), then the MSI-X will be still masked so no interrupt will be received by the driver. Fixes: 1738cd3ed342 ("Add a driver for Amazon Elastic Network Adapters (ENA)") Signed-off-by: Netanel Belgazal Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_netdev.c | 41 +++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 7c1214d78855..0e3c60c7eccf 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -1078,6 +1078,26 @@ inline void ena_adjust_intr_moderation(struct ena_ring *rx_ring, rx_ring->per_napi_bytes = 0; } +static inline void ena_unmask_interrupt(struct ena_ring *tx_ring, + struct ena_ring *rx_ring) +{ + struct ena_eth_io_intr_reg intr_reg; + + /* Update intr register: rx intr delay, + * tx intr delay and interrupt unmask + */ + ena_com_update_intr_reg(&intr_reg, + rx_ring->smoothed_interval, + tx_ring->smoothed_interval, + true); + + /* It is a shared MSI-X. + * Tx and Rx CQ have pointer to it. + * So we use one of them to reach the intr reg + */ + ena_com_unmask_intr(rx_ring->ena_com_io_cq, &intr_reg); +} + static inline void ena_update_ring_numa_node(struct ena_ring *tx_ring, struct ena_ring *rx_ring) { @@ -1108,7 +1128,6 @@ static int ena_io_poll(struct napi_struct *napi, int budget) { struct ena_napi *ena_napi = container_of(napi, struct ena_napi, napi); struct ena_ring *tx_ring, *rx_ring; - struct ena_eth_io_intr_reg intr_reg; u32 tx_work_done; u32 rx_work_done; @@ -1149,22 +1168,9 @@ static int ena_io_poll(struct napi_struct *napi, int budget) if (ena_com_get_adaptive_moderation_enabled(rx_ring->ena_dev)) ena_adjust_intr_moderation(rx_ring, tx_ring); - /* Update intr register: rx intr delay, - * tx intr delay and interrupt unmask - */ - ena_com_update_intr_reg(&intr_reg, - rx_ring->smoothed_interval, - tx_ring->smoothed_interval, - true); - - /* It is a shared MSI-X. - * Tx and Rx CQ have pointer to it. - * So we use one of them to reach the intr reg - */ - ena_com_unmask_intr(rx_ring->ena_com_io_cq, &intr_reg); + ena_unmask_interrupt(tx_ring, rx_ring); } - ena_update_ring_numa_node(tx_ring, rx_ring); ret = rx_work_done; @@ -1485,6 +1491,11 @@ static int ena_up_complete(struct ena_adapter *adapter) ena_napi_enable_all(adapter); + /* Enable completion queues interrupt */ + for (i = 0; i < adapter->num_queues; i++) + ena_unmask_interrupt(&adapter->tx_ring[i], + &adapter->rx_ring[i]); + /* schedule napi in case we had pending packets * from the last time we disable napi */ From 2d2c600a917127f16f179d5a88fc44ba3ed263ed Mon Sep 17 00:00:00 2001 From: Netanel Belgazal Date: Sun, 11 Jun 2017 15:42:45 +0300 Subject: [PATCH 62/91] net: ena: add missing return when ena_com_get_io_handlers() fails Fixes: 1738cd3ed342 ("Add a driver for Amazon Elastic Network Adapters (ENA)") Signed-off-by: Netanel Belgazal Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_netdev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 0e3c60c7eccf..1e71e89e1e18 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -1543,6 +1543,7 @@ static int ena_create_io_tx_queue(struct ena_adapter *adapter, int qid) "Failed to get TX queue handlers. TX queue num %d rc: %d\n", qid, rc); ena_com_destroy_io_queue(ena_dev, ena_qid); + return rc; } ena_com_update_numa_node(tx_ring->ena_com_io_cq, ctx.numa_node); @@ -1607,6 +1608,7 @@ static int ena_create_io_rx_queue(struct ena_adapter *adapter, int qid) "Failed to get RX queue handlers. RX queue num %d rc: %d\n", qid, rc); ena_com_destroy_io_queue(ena_dev, ena_qid); + return rc; } ena_com_update_numa_node(rx_ring->ena_com_io_cq, ctx.numa_node); From 661d2b0ccef6a63f48b61105cf7be17403d1db01 Mon Sep 17 00:00:00 2001 From: Netanel Belgazal Date: Sun, 11 Jun 2017 15:42:46 +0300 Subject: [PATCH 63/91] net: ena: fix race condition between submit and completion admin command Bug: "Completion context is occupied" error printout will be noticed in dmesg. This error will cause the admin command to fail, which will lead to an ena_probe() failure or a watchdog reset (depends on which admin command failed). Root cause: __ena_com_submit_admin_cmd() is the function that submits new entries to the admin queue. The function have a check that makes sure the queue is not full and the function does not override any outstanding command. It uses head and tail indexes for this check. The head is increased by ena_com_handle_admin_completion() which runs from interrupt context, and the tail index is increased by the submit function (the function is running under ->q_lock, so there is no risk of multithread increment). Each command is associated with a completion context. This context allocated before call to __ena_com_submit_admin_cmd() and freed by ena_com_wait_and_process_admin_cq_interrupts(), right after the command was completed. This can lead to a state where the head was increased, the check passed, but the completion context is still in use. Solution: Use the atomic variable ->outstanding_cmds instead of using the head and the tail indexes. This variable is safe for use since it is bumped in get_comp_ctx() in __ena_com_submit_admin_cmd() and is freed by comp_ctxt_release() Fixes: 1738cd3ed342 ("Add a driver for Amazon Elastic Network Adapters (ENA)") Signed-off-by: Netanel Belgazal Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_com.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index e1c2fab6292f..ea60b9e67acb 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -232,11 +232,9 @@ static struct ena_comp_ctx *__ena_com_submit_admin_cmd(struct ena_com_admin_queu tail_masked = admin_queue->sq.tail & queue_size_mask; /* In case of queue FULL */ - cnt = admin_queue->sq.tail - admin_queue->sq.head; + cnt = atomic_read(&admin_queue->outstanding_cmds); if (cnt >= admin_queue->q_depth) { - pr_debug("admin queue is FULL (tail %d head %d depth: %d)\n", - admin_queue->sq.tail, admin_queue->sq.head, - admin_queue->q_depth); + pr_debug("admin queue is full.\n"); admin_queue->stats.out_of_space++; return ERR_PTR(-ENOSPC); } From 0857d92f71b6cb75281fde913554b2d5436c394b Mon Sep 17 00:00:00 2001 From: Netanel Belgazal Date: Sun, 11 Jun 2017 15:42:47 +0300 Subject: [PATCH 64/91] net: ena: add missing unmap bars on device removal This patch also change the mapping functions to devm_ functions Fixes: 1738cd3ed342 ("Add a driver for Amazon Elastic Network Adapters (ENA)") Signed-off-by: Netanel Belgazal Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_netdev.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 1e71e89e1e18..4e9fbddd3b47 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -2853,6 +2853,11 @@ static void ena_release_bars(struct ena_com_dev *ena_dev, struct pci_dev *pdev) { int release_bars; + if (ena_dev->mem_bar) + devm_iounmap(&pdev->dev, ena_dev->mem_bar); + + devm_iounmap(&pdev->dev, ena_dev->reg_bar); + release_bars = pci_select_bars(pdev, IORESOURCE_MEM) & ENA_BAR_MASK; pci_release_selected_regions(pdev, release_bars); } @@ -2940,8 +2945,9 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_free_ena_dev; } - ena_dev->reg_bar = ioremap(pci_resource_start(pdev, ENA_REG_BAR), - pci_resource_len(pdev, ENA_REG_BAR)); + ena_dev->reg_bar = devm_ioremap(&pdev->dev, + pci_resource_start(pdev, ENA_REG_BAR), + pci_resource_len(pdev, ENA_REG_BAR)); if (!ena_dev->reg_bar) { dev_err(&pdev->dev, "failed to remap regs bar\n"); rc = -EFAULT; @@ -2961,8 +2967,9 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ena_set_push_mode(pdev, ena_dev, &get_feat_ctx); if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { - ena_dev->mem_bar = ioremap_wc(pci_resource_start(pdev, ENA_MEM_BAR), - pci_resource_len(pdev, ENA_MEM_BAR)); + ena_dev->mem_bar = devm_ioremap_wc(&pdev->dev, + pci_resource_start(pdev, ENA_MEM_BAR), + pci_resource_len(pdev, ENA_MEM_BAR)); if (!ena_dev->mem_bar) { rc = -EFAULT; goto err_device_destroy; From a3af7c18cfe545a711e5df7491b7d6df71eba2ff Mon Sep 17 00:00:00 2001 From: Netanel Belgazal Date: Sun, 11 Jun 2017 15:42:48 +0300 Subject: [PATCH 65/91] net: ena: fix theoretical Rx hang on low memory systems For the rare case where the device runs out of free rx buffer descriptors (in case of pressure on kernel memory), and the napi handler continuously fail to refill new Rx descriptors until device rx queue totally runs out of all free rx buffers to post incoming packet, leading to a deadlock: * The device won't send interrupts since all the new Rx packets will be dropped. * The napi handler won't try to allocate new Rx descriptors since allocation is part of NAPI that's not being invoked any more The fix involves detecting this scenario and rescheduling NAPI (to refill buffers) by the keepalive/watchdog task. Fixes: 1738cd3ed342 ("Add a driver for Amazon Elastic Network Adapters (ENA)") Signed-off-by: Netanel Belgazal Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_ethtool.c | 1 + drivers/net/ethernet/amazon/ena/ena_netdev.c | 55 +++++++++++++++++++ drivers/net/ethernet/amazon/ena/ena_netdev.h | 2 + 3 files changed, 58 insertions(+) diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index 67b2338f8fb3..533b2fbdeef1 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -94,6 +94,7 @@ static const struct ena_stats ena_stats_rx_strings[] = { ENA_STAT_RX_ENTRY(dma_mapping_err), ENA_STAT_RX_ENTRY(bad_desc_num), ENA_STAT_RX_ENTRY(rx_copybreak_pkt), + ENA_STAT_RX_ENTRY(empty_rx_ring), }; static const struct ena_stats ena_stats_ena_com_strings[] = { diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 4e9fbddd3b47..3c366bfbbab1 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -190,6 +190,7 @@ static void ena_init_io_rings(struct ena_adapter *adapter) rxr->sgl_size = adapter->max_rx_sgl_size; rxr->smoothed_interval = ena_com_get_nonadaptive_moderation_interval_rx(ena_dev); + rxr->empty_rx_queue = 0; } } @@ -2619,6 +2620,58 @@ static void check_for_missing_tx_completions(struct ena_adapter *adapter) adapter->last_monitored_tx_qid = i % adapter->num_queues; } +/* trigger napi schedule after 2 consecutive detections */ +#define EMPTY_RX_REFILL 2 +/* For the rare case where the device runs out of Rx descriptors and the + * napi handler failed to refill new Rx descriptors (due to a lack of memory + * for example). + * This case will lead to a deadlock: + * The device won't send interrupts since all the new Rx packets will be dropped + * The napi handler won't allocate new Rx descriptors so the device will be + * able to send new packets. + * + * This scenario can happen when the kernel's vm.min_free_kbytes is too small. + * It is recommended to have at least 512MB, with a minimum of 128MB for + * constrained environment). + * + * When such a situation is detected - Reschedule napi + */ +static void check_for_empty_rx_ring(struct ena_adapter *adapter) +{ + struct ena_ring *rx_ring; + int i, refill_required; + + if (!test_bit(ENA_FLAG_DEV_UP, &adapter->flags)) + return; + + if (test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags)) + return; + + for (i = 0; i < adapter->num_queues; i++) { + rx_ring = &adapter->rx_ring[i]; + + refill_required = + ena_com_sq_empty_space(rx_ring->ena_com_io_sq); + if (unlikely(refill_required == (rx_ring->ring_size - 1))) { + rx_ring->empty_rx_queue++; + + if (rx_ring->empty_rx_queue >= EMPTY_RX_REFILL) { + u64_stats_update_begin(&rx_ring->syncp); + rx_ring->rx_stats.empty_rx_ring++; + u64_stats_update_end(&rx_ring->syncp); + + netif_err(adapter, drv, adapter->netdev, + "trigger refill for ring %d\n", i); + + napi_schedule(rx_ring->napi); + rx_ring->empty_rx_queue = 0; + } + } else { + rx_ring->empty_rx_queue = 0; + } + } +} + /* Check for keep alive expiration */ static void check_for_missing_keep_alive(struct ena_adapter *adapter) { @@ -2673,6 +2726,8 @@ static void ena_timer_service(unsigned long data) check_for_missing_tx_completions(adapter); + check_for_empty_rx_ring(adapter); + if (debug_area) ena_dump_stats_to_buf(adapter, debug_area); diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 0e22bce6239d..8828f1d6dd22 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -184,6 +184,7 @@ struct ena_stats_rx { u64 dma_mapping_err; u64 bad_desc_num; u64 rx_copybreak_pkt; + u64 empty_rx_ring; }; struct ena_ring { @@ -231,6 +232,7 @@ struct ena_ring { struct ena_stats_tx tx_stats; struct ena_stats_rx rx_stats; }; + int empty_rx_queue; } ____cacheline_aligned; struct ena_stats_dev { From a2cc5198dac102775b21787752a2e0afe44ad311 Mon Sep 17 00:00:00 2001 From: Netanel Belgazal Date: Sun, 11 Jun 2017 15:42:49 +0300 Subject: [PATCH 66/91] net: ena: disable admin msix while working in polling mode Fixes: 1738cd3ed342 ("Add a driver for Amazon Elastic Network Adapters (ENA)") Signed-off-by: Netanel Belgazal Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_com.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index ea60b9e67acb..f5b237e0bd60 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -61,6 +61,8 @@ #define ENA_MMIO_READ_TIMEOUT 0xFFFFFFFF +#define ENA_REGS_ADMIN_INTR_MASK 1 + /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ @@ -1454,6 +1456,12 @@ void ena_com_admin_destroy(struct ena_com_dev *ena_dev) void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling) { + u32 mask_value = 0; + + if (polling) + mask_value = ENA_REGS_ADMIN_INTR_MASK; + + writel(mask_value, ena_dev->reg_bar + ENA_REGS_INTR_MASK_OFF); ena_dev->admin_queue.polling = polling; } From 800c55cb76be6617232ef50a2be29830f3aa8e5c Mon Sep 17 00:00:00 2001 From: Netanel Belgazal Date: Sun, 11 Jun 2017 15:42:50 +0300 Subject: [PATCH 67/91] net: ena: bug fix in lost tx packets detection mechanism check_for_missing_tx_completions() is called from a timer task and looking for lost tx packets. The old implementation accumulate all the lost tx packets and did not check if those packets were retrieved on a later stage. This cause to a situation where the driver reset the device for no reason. Fixes: 1738cd3ed342 ("Add a driver for Amazon Elastic Network Adapters (ENA)") Signed-off-by: Netanel Belgazal Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_ethtool.c | 1 - drivers/net/ethernet/amazon/ena/ena_netdev.c | 66 +++++++++++-------- drivers/net/ethernet/amazon/ena/ena_netdev.h | 14 +++- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index 533b2fbdeef1..3ee55e2fd694 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -80,7 +80,6 @@ static const struct ena_stats ena_stats_tx_strings[] = { ENA_STAT_TX_ENTRY(tx_poll), ENA_STAT_TX_ENTRY(doorbells), ENA_STAT_TX_ENTRY(prepare_ctx_err), - ENA_STAT_TX_ENTRY(missing_tx_comp), ENA_STAT_TX_ENTRY(bad_req_id), }; diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 3c366bfbbab1..4f16ed38bcf3 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -1995,6 +1995,7 @@ static netdev_tx_t ena_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_info->tx_descs = nb_hw_desc; tx_info->last_jiffies = jiffies; + tx_info->print_once = 0; tx_ring->next_to_use = ENA_TX_RING_IDX_NEXT(next_to_use, tx_ring->ring_size); @@ -2564,13 +2565,44 @@ static void ena_fw_reset_device(struct work_struct *work) "Reset attempt failed. Can not reset the device\n"); } -static void check_for_missing_tx_completions(struct ena_adapter *adapter) +static int check_missing_comp_in_queue(struct ena_adapter *adapter, + struct ena_ring *tx_ring) { struct ena_tx_buffer *tx_buf; unsigned long last_jiffies; + u32 missed_tx = 0; + int i; + + for (i = 0; i < tx_ring->ring_size; i++) { + tx_buf = &tx_ring->tx_buffer_info[i]; + last_jiffies = tx_buf->last_jiffies; + if (unlikely(last_jiffies && + time_is_before_jiffies(last_jiffies + TX_TIMEOUT))) { + if (!tx_buf->print_once) + netif_notice(adapter, tx_err, adapter->netdev, + "Found a Tx that wasn't completed on time, qid %d, index %d.\n", + tx_ring->qid, i); + + tx_buf->print_once = 1; + missed_tx++; + + if (unlikely(missed_tx > MAX_NUM_OF_TIMEOUTED_PACKETS)) { + netif_err(adapter, tx_err, adapter->netdev, + "The number of lost tx completions is above the threshold (%d > %d). Reset the device\n", + missed_tx, MAX_NUM_OF_TIMEOUTED_PACKETS); + set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags); + return -EIO; + } + } + } + + return 0; +} + +static void check_for_missing_tx_completions(struct ena_adapter *adapter) +{ struct ena_ring *tx_ring; - int i, j, budget; - u32 missed_tx; + int i, budget, rc; /* Make sure the driver doesn't turn the device in other process */ smp_rmb(); @@ -2586,31 +2618,9 @@ static void check_for_missing_tx_completions(struct ena_adapter *adapter) for (i = adapter->last_monitored_tx_qid; i < adapter->num_queues; i++) { tx_ring = &adapter->tx_ring[i]; - for (j = 0; j < tx_ring->ring_size; j++) { - tx_buf = &tx_ring->tx_buffer_info[j]; - last_jiffies = tx_buf->last_jiffies; - if (unlikely(last_jiffies && time_is_before_jiffies(last_jiffies + TX_TIMEOUT))) { - netif_notice(adapter, tx_err, adapter->netdev, - "Found a Tx that wasn't completed on time, qid %d, index %d.\n", - tx_ring->qid, j); - - u64_stats_update_begin(&tx_ring->syncp); - missed_tx = tx_ring->tx_stats.missing_tx_comp++; - u64_stats_update_end(&tx_ring->syncp); - - /* Clear last jiffies so the lost buffer won't - * be counted twice. - */ - tx_buf->last_jiffies = 0; - - if (unlikely(missed_tx > MAX_NUM_OF_TIMEOUTED_PACKETS)) { - netif_err(adapter, tx_err, adapter->netdev, - "The number of lost tx completion is above the threshold (%d > %d). Reset the device\n", - missed_tx, MAX_NUM_OF_TIMEOUTED_PACKETS); - set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags); - } - } - } + rc = check_missing_comp_in_queue(adapter, tx_ring); + if (unlikely(rc)) + return; budget--; if (!budget) diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 8828f1d6dd22..88b5e5612338 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -146,7 +146,18 @@ struct ena_tx_buffer { u32 tx_descs; /* num of buffers used by this skb */ u32 num_of_bufs; - /* Save the last jiffies to detect missing tx packets */ + + /* Used for detect missing tx packets to limit the number of prints */ + u32 print_once; + /* Save the last jiffies to detect missing tx packets + * + * sets to non zero value on ena_start_xmit and set to zero on + * napi and timer_Service_routine. + * + * while this value is not protected by lock, + * a given packet is not expected to be handled by ena_start_xmit + * and by napi/timer_service at the same time. + */ unsigned long last_jiffies; struct ena_com_buf bufs[ENA_PKT_MAX_BUFS]; } ____cacheline_aligned; @@ -170,7 +181,6 @@ struct ena_stats_tx { u64 napi_comp; u64 tx_poll; u64 doorbells; - u64 missing_tx_comp; u64 bad_req_id; }; From e7ff7efae5708513a795e329909ccbe2ac367b1a Mon Sep 17 00:00:00 2001 From: Netanel Belgazal Date: Sun, 11 Jun 2017 15:42:51 +0300 Subject: [PATCH 68/91] net: ena: update ena driver to version 1.1.7 Signed-off-by: Netanel Belgazal Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_netdev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 88b5e5612338..a4d3d5e21068 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -45,7 +45,7 @@ #define DRV_MODULE_VER_MAJOR 1 #define DRV_MODULE_VER_MINOR 1 -#define DRV_MODULE_VER_SUBMINOR 2 +#define DRV_MODULE_VER_SUBMINOR 7 #define DRV_MODULE_NAME "ena" #ifndef DRV_MODULE_VERSION From 4b1f0d33db7d5bf92b5623e3ea2066e2de3999e3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 10 Jun 2017 16:30:17 -0400 Subject: [PATCH 69/91] net: ipmr: Fix some mroute forwarding issues in vrf's This patch fixes two issues: 1) When forwarding on *,G mroutes that are in a vrf, the kernel was dropping information about the actual incoming interface when calling ip_mr_forward from ip_mr_input. This caused ip_mr_forward to send the multicast packet back out the incoming interface. Fix this by modifying ip_mr_forward to be handed the correctly resolved dev. 2) When a unresolved cache entry is created we store the incoming skb on the unresolved cache entry and upon mroute resolution from the user space daemon, we attempt to forward the packet. Again we were not resolving to the correct incoming device for a vrf scenario, before calling ip_mr_forward. Fix this by resolving to the correct interface and calling ip_mr_forward with the result. Fixes: e58e41596811 ("net: Enable support for VRF with ipv4 multicast") Signed-off-by: Donald Sharp Acked-by: David Ahern Acked-by: Nikolay Aleksandrov Reviewed-by: Yotam Gigi Signed-off-by: David S. Miller --- net/ipv4/ipmr.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index b4f9622ee9f5..8ae425cad818 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -101,8 +101,8 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id); static void ipmr_free_table(struct mr_table *mrt); static void ip_mr_forward(struct net *net, struct mr_table *mrt, - struct sk_buff *skb, struct mfc_cache *cache, - int local); + struct net_device *dev, struct sk_buff *skb, + struct mfc_cache *cache, int local); static int ipmr_cache_report(struct mr_table *mrt, struct sk_buff *pkt, vifi_t vifi, int assert); static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, @@ -988,7 +988,7 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt, rtnl_unicast(skb, net, NETLINK_CB(skb).portid); } else { - ip_mr_forward(net, mrt, skb, c, 0); + ip_mr_forward(net, mrt, skb->dev, skb, c, 0); } } } @@ -1073,7 +1073,7 @@ static int ipmr_cache_report(struct mr_table *mrt, /* Queue a packet for resolution. It gets locked cache entry! */ static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, - struct sk_buff *skb) + struct sk_buff *skb, struct net_device *dev) { const struct iphdr *iph = ip_hdr(skb); struct mfc_cache *c; @@ -1130,6 +1130,10 @@ static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, kfree_skb(skb); err = -ENOBUFS; } else { + if (dev) { + skb->dev = dev; + skb->skb_iif = dev->ifindex; + } skb_queue_tail(&c->mfc_un.unres.unresolved, skb); err = 0; } @@ -1828,10 +1832,10 @@ static int ipmr_find_vif(struct mr_table *mrt, struct net_device *dev) /* "local" means that we should preserve one skb (for local delivery) */ static void ip_mr_forward(struct net *net, struct mr_table *mrt, - struct sk_buff *skb, struct mfc_cache *cache, - int local) + struct net_device *dev, struct sk_buff *skb, + struct mfc_cache *cache, int local) { - int true_vifi = ipmr_find_vif(mrt, skb->dev); + int true_vifi = ipmr_find_vif(mrt, dev); int psend = -1; int vif, ct; @@ -1853,13 +1857,7 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt, } /* Wrong interface: drop packet and (maybe) send PIM assert. */ - if (mrt->vif_table[vif].dev != skb->dev) { - struct net_device *mdev; - - mdev = l3mdev_master_dev_rcu(mrt->vif_table[vif].dev); - if (mdev == skb->dev) - goto forward; - + if (mrt->vif_table[vif].dev != dev) { if (rt_is_output_route(skb_rtable(skb))) { /* It is our own packet, looped back. * Very complicated situation... @@ -2053,7 +2051,7 @@ int ip_mr_input(struct sk_buff *skb) read_lock(&mrt_lock); vif = ipmr_find_vif(mrt, dev); if (vif >= 0) { - int err2 = ipmr_cache_unresolved(mrt, vif, skb); + int err2 = ipmr_cache_unresolved(mrt, vif, skb, dev); read_unlock(&mrt_lock); return err2; @@ -2064,7 +2062,7 @@ int ip_mr_input(struct sk_buff *skb) } read_lock(&mrt_lock); - ip_mr_forward(net, mrt, skb, cache, local); + ip_mr_forward(net, mrt, dev, skb, cache, local); read_unlock(&mrt_lock); if (local) @@ -2238,7 +2236,7 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb, iph->saddr = saddr; iph->daddr = daddr; iph->version = 0; - err = ipmr_cache_unresolved(mrt, vif, skb2); + err = ipmr_cache_unresolved(mrt, vif, skb2, dev); read_unlock(&mrt_lock); rcu_read_unlock(); return err; From 3500cd73dff48f28f4ba80c171c4c80034d40f76 Mon Sep 17 00:00:00 2001 From: Christian Perle Date: Mon, 12 Jun 2017 10:06:57 +0200 Subject: [PATCH 70/91] proc: snmp6: Use correct type in memset Reading /proc/net/snmp6 yields bogus values on 32 bit kernels. Use "u64" instead of "unsigned long" in sizeof(). Fixes: 4a4857b1c81e ("proc: Reduce cache miss in snmp6_seq_show") Signed-off-by: Christian Perle Signed-off-by: David S. Miller --- net/ipv6/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index cc8e3ae9ca73..e88bcb8ff0fd 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -219,7 +219,7 @@ static void snmp6_seq_show_item64(struct seq_file *seq, void __percpu *mib, u64 buff64[SNMP_MIB_MAX]; int i; - memset(buff64, 0, sizeof(unsigned long) * SNMP_MIB_MAX); + memset(buff64, 0, sizeof(u64) * SNMP_MIB_MAX); snmp_get_cpu_field64_batch(buff64, itemlist, mib, syncpoff); for (i = 0; itemlist[i].name; i++) From 675c8da049fd6556eb2d6cdd745fe812752f07a8 Mon Sep 17 00:00:00 2001 From: "Karicheri, Muralidharan" Date: Mon, 12 Jun 2017 15:06:26 -0400 Subject: [PATCH 71/91] hsr: fix incorrect warning When HSR interface is setup using ip link command, an annoying warning appears with the trace as below:- [ 203.019828] hsr_get_node: Non-HSR frame [ 203.019833] Modules linked in: [ 203.019848] CPU: 0 PID: 158 Comm: sd-resolve Tainted: G W 4.12.0-rc3-00052-g9fa6bf70 #2 [ 203.019853] Hardware name: Generic DRA74X (Flattened Device Tree) [ 203.019869] [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [ 203.019880] [] (show_stack) from [] (dump_stack+0xac/0xe0) [ 203.019894] [] (dump_stack) from [] (__warn+0xd8/0x104) [ 203.019907] [] (__warn) from [] (warn_slowpath_fmt+0x34/0x44) root@am57xx-evm:~# [ 203.019921] [] (warn_slowpath_fmt) from [] (hsr_get_node+0x148/0x170) [ 203.019932] [] (hsr_get_node) from [] (hsr_forward_skb+0x110/0x7c0) [ 203.019942] [] (hsr_forward_skb) from [] (hsr_dev_xmit+0x2c/0x34) [ 203.019954] [] (hsr_dev_xmit) from [] (dev_hard_start_xmit+0xc4/0x3bc) [ 203.019963] [] (dev_hard_start_xmit) from [] (__dev_queue_xmit+0x7c4/0x98c) [ 203.019974] [] (__dev_queue_xmit) from [] (ip6_finish_output2+0x330/0xc1c) [ 203.019983] [] (ip6_finish_output2) from [] (ip6_output+0x58/0x454) [ 203.019994] [] (ip6_output) from [] (mld_sendpack+0x420/0x744) As this is an expected path to hsr_get_node() with frame coming from the master interface, add a check to ensure packet is not from the master port and then warn. Signed-off-by: Murali Karicheri Signed-off-by: David S. Miller --- net/hsr/hsr_forward.c | 3 +-- net/hsr/hsr_framereg.c | 9 +++++++-- net/hsr/hsr_framereg.h | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c index 4ebe2aa3e7d3..04b5450c5a55 100644 --- a/net/hsr/hsr_forward.c +++ b/net/hsr/hsr_forward.c @@ -324,8 +324,7 @@ static int hsr_fill_frame_info(struct hsr_frame_info *frame, unsigned long irqflags; frame->is_supervision = is_supervision_frame(port->hsr, skb); - frame->node_src = hsr_get_node(&port->hsr->node_db, skb, - frame->is_supervision); + frame->node_src = hsr_get_node(port, skb, frame->is_supervision); if (frame->node_src == NULL) return -1; /* Unknown node and !is_supervision, or no mem */ diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index 7ea925816f79..284a9b820df8 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c @@ -158,9 +158,10 @@ struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[], /* Get the hsr_node from which 'skb' was sent. */ -struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb, +struct hsr_node *hsr_get_node(struct hsr_port *port, struct sk_buff *skb, bool is_sup) { + struct list_head *node_db = &port->hsr->node_db; struct hsr_node *node; struct ethhdr *ethhdr; u16 seq_out; @@ -186,7 +187,11 @@ struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb, */ seq_out = hsr_get_skb_sequence_nr(skb) - 1; } else { - WARN_ONCE(1, "%s: Non-HSR frame\n", __func__); + /* this is called also for frames from master port and + * so warn only for non master ports + */ + if (port->type != HSR_PT_MASTER) + WARN_ONCE(1, "%s: Non-HSR frame\n", __func__); seq_out = HSR_SEQNR_START; } diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h index 438b40f98f5a..4e04f0e868e9 100644 --- a/net/hsr/hsr_framereg.h +++ b/net/hsr/hsr_framereg.h @@ -18,7 +18,7 @@ struct hsr_node; struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[], u16 seq_out); -struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb, +struct hsr_node *hsr_get_node(struct hsr_port *port, struct sk_buff *skb, bool is_sup); void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr, struct hsr_port *port); From 6964e53f55837b0c49ed60d36656d2e0ee4fc27b Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 12 Jun 2017 15:38:36 -0700 Subject: [PATCH 72/91] i40e: fix handling of HW ATR eviction A recent commit to refactor the driver and remove the hw_disabled_flags field accidentally introduced two regressions. First, we overwrote pf->flags which removed various key flags including the MSI-X settings. Additionally, it was intended that we have now two flags, HW_ATR_EVICT_CAPABLE and HW_ATR_EVICT_ENABLED, but this was not done, and we accidentally were mis-using HW_ATR_EVICT_CAPABLE everywhere. This patch adds the missing piece, HW_ATR_EVICT_ENABLED, and safely updates pf->flags instead of overwriting it. Without this patch we will have many problems including disabling MSI-X support, and we'll attempt to use HW ATR eviction on devices which do not support it. Fixes: 47994c119a36 ("i40e: remove hw_disabled_flags in favor of using separate flag bits", 2017-04-19) Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_main.c | 7 ++++--- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index cdde3cc28fb5..44d9610f7a15 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -399,6 +399,7 @@ struct i40e_pf { #define I40E_FLAG_RX_CSUM_ENABLED BIT_ULL(1) #define I40E_FLAG_MSI_ENABLED BIT_ULL(2) #define I40E_FLAG_MSIX_ENABLED BIT_ULL(3) +#define I40E_FLAG_HW_ATR_EVICT_ENABLED BIT_ULL(4) #define I40E_FLAG_RSS_ENABLED BIT_ULL(6) #define I40E_FLAG_VMDQ_ENABLED BIT_ULL(7) #define I40E_FLAG_IWARP_ENABLED BIT_ULL(10) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 7a8eb486b9ea..894c8e57ba00 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -224,7 +224,7 @@ static const struct i40e_priv_flags i40e_gstrings_priv_flags[] = { I40E_PRIV_FLAG("LinkPolling", I40E_FLAG_LINK_POLLING_ENABLED, 0), I40E_PRIV_FLAG("flow-director-atr", I40E_FLAG_FD_ATR_ENABLED, 0), I40E_PRIV_FLAG("veb-stats", I40E_FLAG_VEB_STATS_ENABLED, 0), - I40E_PRIV_FLAG("hw-atr-eviction", I40E_FLAG_HW_ATR_EVICT_CAPABLE, 0), + I40E_PRIV_FLAG("hw-atr-eviction", I40E_FLAG_HW_ATR_EVICT_ENABLED, 0), I40E_PRIV_FLAG("legacy-rx", I40E_FLAG_LEGACY_RX, 0), }; @@ -4092,7 +4092,7 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags) /* Only allow ATR evict on hardware that is capable of handling it */ if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) - pf->flags &= ~I40E_FLAG_HW_ATR_EVICT_CAPABLE; + pf->flags &= ~I40E_FLAG_HW_ATR_EVICT_ENABLED; if (changed_flags & I40E_FLAG_TRUE_PROMISC_SUPPORT) { u16 sw_flags = 0, valid_flags = 0; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 150caf6ca2b4..a7a4b28b4144 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8821,11 +8821,12 @@ static int i40e_sw_init(struct i40e_pf *pf) (pf->hw.aq.api_min_ver > 4))) { /* Supported in FW API version higher than 1.4 */ pf->flags |= I40E_FLAG_GENEVE_OFFLOAD_CAPABLE; - pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE; - } else { - pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE; } + /* Enable HW ATR eviction if possible */ + if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) + pf->flags |= I40E_FLAG_HW_ATR_EVICT_ENABLED; + pf->eeprom_version = 0xDEAD; pf->lan_veb = I40E_NO_VEB; pf->lan_vsi = I40E_NO_VSI; diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index cd894f4023b1..77115c25d96f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2341,7 +2341,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb, /* Due to lack of space, no more new filters can be programmed */ if (th->syn && (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED)) return; - if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) { + if (pf->flags & I40E_FLAG_HW_ATR_EVICT_ENABLED) { /* HW ATR eviction will take care of removing filters on FIN * and RST packets. */ @@ -2403,7 +2403,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb, I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) & I40E_TXD_FLTR_QW1_CNTINDEX_MASK; - if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) + if (pf->flags & I40E_FLAG_HW_ATR_EVICT_ENABLED) dtype_cmd |= I40E_TXD_FLTR_QW1_ATR_MASK; fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(flex_ptype); From 769dc04db3ed8484798aceb015b94deacc2ba557 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 8 Jun 2017 14:00:49 +0300 Subject: [PATCH 73/91] mac80211: don't look at the PM bit of BAR frames When a peer sends a BAR frame with PM bit clear, we should not modify its PM state as madated by the spec in 802.11-20012 10.2.1.2. Cc: stable@vger.kernel.org Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 1f75280ba26c..3674fe3d67dc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1613,12 +1613,16 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) */ if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) && !ieee80211_has_morefrags(hdr->frame_control) && + !ieee80211_is_back_req(hdr->frame_control) && !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && (rx->sdata->vif.type == NL80211_IFTYPE_AP || rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && - /* PM bit is only checked in frames where it isn't reserved, + /* + * PM bit is only checked in frames where it isn't reserved, * in AP mode it's reserved in non-bufferable management frames * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field) + * BAR frames should be ignored as specified in + * IEEE 802.11-2012 10.2.1.2. */ (!ieee80211_is_mgmt(hdr->frame_control) || ieee80211_is_bufferable_mmpdu(hdr->frame_control))) { From 204a7dbcb27bc4b461f42d7f96fdc875eb677f2f Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Mon, 12 Jun 2017 10:44:58 +0300 Subject: [PATCH 74/91] mac80211: Fix incorrect condition when checking rx timestamp If the driver reports the rx timestamp at PLCP start, mac80211 can only handle legacy encoding, but the code checks that the encoding is not legacy. Fix this. Fixes: da6a4352e7c8 ("mac80211: separate encoding/bandwidth from flags") Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 665501ac358f..5e002f62c235 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1531,7 +1531,7 @@ ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status) return true; /* can't handle non-legacy preamble yet */ if (status->flag & RX_FLAG_MACTIME_PLCP_START && - status->encoding != RX_ENC_LEGACY) + status->encoding == RX_ENC_LEGACY) return true; return false; } From 44f6d42cbd6e4c1d4d25f19502dd5f27aedf89d4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 10 Jun 2017 13:52:44 +0300 Subject: [PATCH 75/91] mac80211: remove 5/10 MHz rate code from station MLME There's no need for the station MLME code to handle bitrates for 5 or 10 MHz channels when it can't ever create such a configuration. Remove the unnecessary code. Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0ea9712bd99e..2f46db7d3afc 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -601,7 +601,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) struct ieee80211_supported_band *sband; struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_channel *chan; - u32 rate_flags, rates = 0; + u32 rates = 0; sdata_assert_lock(sdata); @@ -612,7 +612,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) return; } chan = chanctx_conf->def.chan; - rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); rcu_read_unlock(); sband = local->hw.wiphy->bands[chan->band]; shift = ieee80211_vif_get_shift(&sdata->vif); @@ -636,9 +635,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) */ rates_len = 0; for (i = 0; i < sband->n_bitrates; i++) { - if ((rate_flags & sband->bitrates[i].flags) - != rate_flags) - continue; rates |= BIT(i); rates_len++; } @@ -2818,7 +2814,7 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, u32 *rates, u32 *basic_rates, bool *have_higher_than_11mbit, int *min_rate, int *min_rate_index, - int shift, u32 rate_flags) + int shift) { int i, j; @@ -2846,8 +2842,6 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, int brate; br = &sband->bitrates[j]; - if ((rate_flags & br->flags) != rate_flags) - continue; brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5); if (brate == rate) { @@ -4411,27 +4405,15 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, u32 rates = 0, basic_rates = 0; bool have_higher_than_11mbit; int min_rate = INT_MAX, min_rate_index = -1; - struct ieee80211_chanctx_conf *chanctx_conf; const struct cfg80211_bss_ies *ies; int shift = ieee80211_vif_get_shift(&sdata->vif); - u32 rate_flags; - - rcu_read_lock(); - chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); - if (WARN_ON(!chanctx_conf)) { - rcu_read_unlock(); - sta_info_free(local, new_sta); - return -EINVAL; - } - rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); - rcu_read_unlock(); ieee80211_get_rates(sband, bss->supp_rates, bss->supp_rates_len, &rates, &basic_rates, &have_higher_than_11mbit, &min_rate, &min_rate_index, - shift, rate_flags); + shift); /* * This used to be a workaround for basic rates missing From c87905bec5dad66aa6bb43d11502cafdb33e07db Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 10 Jun 2017 13:52:43 +0300 Subject: [PATCH 76/91] mac80211: set bss_info data before configuring the channel When mac80211 changes the channel, it also calls into the driver's bss_info_changed() callback, e.g. with BSS_CHANGED_IDLE. The driver may, like iwlwifi does, access more data from bss_info in that case and iwlwifi accesses the basic_rates bitmap, but if changing from a band with more (basic) rates to one with fewer, an out-of-bounds access of the rate array may result. While we can't avoid having invalid data at some point in time, we can avoid having it while we call the driver - so set up all the data before configuring the channel, and then apply it afterwards. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=195677 Reported-by: Johannes Hirte Tested-by: Johannes Hirte Debugged-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2f46db7d3afc..cc8e6ea1b27e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -4392,15 +4392,19 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, return -ENOMEM; } - if (new_sta || override) { - err = ieee80211_prep_channel(sdata, cbss); - if (err) { - if (new_sta) - sta_info_free(local, new_sta); - return -EINVAL; - } - } - + /* + * Set up the information for the new channel before setting the + * new channel. We can't - completely race-free - change the basic + * rates bitmap and the channel (sband) that it refers to, but if + * we set it up before we at least avoid calling into the driver's + * bss_info_changed() method with invalid information (since we do + * call that from changing the channel - only for IDLE and perhaps + * some others, but ...). + * + * So to avoid that, just set up all the new information before the + * channel, but tell the driver to apply it only afterwards, since + * it might need the new channel for that. + */ if (new_sta) { u32 rates = 0, basic_rates = 0; bool have_higher_than_11mbit; @@ -4471,8 +4475,22 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, sdata->vif.bss_conf.sync_dtim_count = 0; } rcu_read_unlock(); + } - /* tell driver about BSSID, basic rates and timing */ + if (new_sta || override) { + err = ieee80211_prep_channel(sdata, cbss); + if (err) { + if (new_sta) + sta_info_free(local, new_sta); + return -EINVAL; + } + } + + if (new_sta) { + /* + * tell driver about BSSID, basic rates and timing + * this was set up above, before setting the channel + */ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES | BSS_CHANGED_BEACON_INT); From 98c67d187db7808b1f3c95f2110dd4392d034182 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 10 Jun 2017 04:59:12 +0200 Subject: [PATCH 77/91] mac80211/wpa: use constant time memory comparison for MACs Otherwise, we enable all sorts of forgeries via timing attack. Signed-off-by: Jason A. Donenfeld Cc: Johannes Berg Cc: linux-wireless@vger.kernel.org Cc: stable@vger.kernel.org Signed-off-by: Johannes Berg --- net/mac80211/wpa.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index c1ef22df865f..cc19614ff4e6 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "ieee80211_i.h" #include "michael.h" @@ -153,7 +154,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; michael_mic(key, hdr, data, data_len, mic); - if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) + if (crypto_memneq(mic, data + data_len, MICHAEL_MIC_LEN)) goto mic_fail; /* remove Michael MIC from payload */ @@ -1048,7 +1049,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) bip_aad(skb, aad); ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, skb->data + 24, skb->len - 24, mic); - if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { + if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { key->u.aes_cmac.icverrors++; return RX_DROP_UNUSABLE; } @@ -1098,7 +1099,7 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx) bip_aad(skb, aad); ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad, skb->data + 24, skb->len - 24, mic); - if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { + if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { key->u.aes_cmac.icverrors++; return RX_DROP_UNUSABLE; } @@ -1202,7 +1203,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx) if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce, skb->data + 24, skb->len - 24, mic) < 0 || - memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { + crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { key->u.aes_gmac.icverrors++; return RX_DROP_UNUSABLE; } From b3dd8279659f14f3624bb32559782d699fa6f7d1 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sat, 10 Jun 2017 13:52:45 +0300 Subject: [PATCH 78/91] mac80211: don't send SMPS action frame in AP mode when not needed mac80211 allows to modify the SMPS state of an AP both, when it is started, and after it has been started. Such a change will trigger an action frame to all the peers that are currently connected, and will be remembered so that new peers will get notified as soon as they connect (since the SMPS setting in the beacon may not be the right one). This means that we need to remember the SMPS state currently requested as well as the SMPS state that was configured initially (and advertised in the beacon). The former is bss->req_smps and the latter is sdata->smps_mode. Initially, the AP interface could only be started with SMPS_OFF, which means that sdata->smps_mode was SMPS_OFF always. Later, a nl80211 API was added to be able to start an AP with a different AP mode. That code forgot to update bss->req_smps and because of that, if the AP interface was started with SMPS_DYNAMIC, we had: sdata->smps_mode = SMPS_DYNAMIC bss->req_smps = SMPS_OFF That configuration made mac80211 think it needs to fire off an action frame to any new station connecting to the AP in order to let it know that the actual SMPS configuration is SMPS_OFF. Fix that by properly setting bss->req_smps in ieee80211_start_ap. Fixes: f69931748730 ("mac80211: set smps_mode according to ap params") Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6c2e6060cd54..4a388fe8c2d1 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -902,6 +902,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, default: return -EINVAL; } + sdata->u.ap.req_smps = sdata->smps_mode; + sdata->needed_rx_chains = sdata->local->rx_chains; sdata->vif.bss_conf.beacon_int = params->beacon_interval; From 97d8b6e3b8538198aefb0003342920a82e062147 Mon Sep 17 00:00:00 2001 From: Ashwanth Goli Date: Tue, 13 Jun 2017 16:54:55 +0530 Subject: [PATCH 79/91] net: rps: fix uninitialized symbol warning This patch fixes uninitialized symbol warning that got introduced by the following commit 773fc8f6e8d6 ("net: rps: send out pending IPI's on CPU hotplug") Signed-off-by: Ashwanth Goli Signed-off-by: David S. Miller --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 54bb8d99d26a..6d60149287a1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -8203,7 +8203,7 @@ static int dev_cpu_dead(unsigned int oldcpu) struct sk_buff **list_skb; struct sk_buff *skb; unsigned int cpu; - struct softnet_data *sd, *oldsd, *remsd; + struct softnet_data *sd, *oldsd, *remsd = NULL; local_irq_disable(); cpu = smp_processor_id(); From eb3c28c15555212227cfa8b9a3baa21ad5982a19 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 12 Jun 2017 13:56:51 +0200 Subject: [PATCH 80/91] r8152: give the device version Getting the device version out of the driver really aids debugging. Signed-off-by: Oliver Neukum Signed-off-by: David S. Miller --- drivers/net/usb/r8152.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index ddc62cb69be8..1a419a45e2a2 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -4368,6 +4368,8 @@ static u8 rtl_get_version(struct usb_interface *intf) break; } + dev_dbg(&intf->dev, "Detected version 0x%04x\n", version); + return version; } From c38b7d327aafd1e3ad7ff53eefac990673b65667 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Mon, 12 Jun 2017 09:52:26 -0700 Subject: [PATCH 81/91] igmp: acquire pmc lock for ip_mc_clear_src() Andrey reported a use-after-free in add_grec(): for (psf = *psf_list; psf; psf = psf_next) { ... psf_next = psf->sf_next; where the struct ip_sf_list's were already freed by: kfree+0xe8/0x2b0 mm/slub.c:3882 ip_mc_clear_src+0x69/0x1c0 net/ipv4/igmp.c:2078 ip_mc_dec_group+0x19a/0x470 net/ipv4/igmp.c:1618 ip_mc_drop_socket+0x145/0x230 net/ipv4/igmp.c:2609 inet_release+0x4e/0x1c0 net/ipv4/af_inet.c:411 sock_release+0x8d/0x1e0 net/socket.c:597 sock_close+0x16/0x20 net/socket.c:1072 This happens because we don't hold pmc->lock in ip_mc_clear_src() and a parallel mr_ifc_timer timer could jump in and access them. The RCU lock is there but it is merely for pmc itself, this spinlock could actually ensure we don't access them in parallel. Thanks to Eric and Long for discussion on this bug. Reported-by: Andrey Konovalov Cc: Eric Dumazet Cc: Xin Long Signed-off-by: Cong Wang Reviewed-by: Xin Long Signed-off-by: David S. Miller --- net/ipv4/igmp.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 44fd86de2823..8f6b5bbcbf69 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -2071,21 +2071,26 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode, static void ip_mc_clear_src(struct ip_mc_list *pmc) { - struct ip_sf_list *psf, *nextpsf; + struct ip_sf_list *psf, *nextpsf, *tomb, *sources; - for (psf = pmc->tomb; psf; psf = nextpsf) { - nextpsf = psf->sf_next; - kfree(psf); - } + spin_lock_bh(&pmc->lock); + tomb = pmc->tomb; pmc->tomb = NULL; - for (psf = pmc->sources; psf; psf = nextpsf) { - nextpsf = psf->sf_next; - kfree(psf); - } + sources = pmc->sources; pmc->sources = NULL; pmc->sfmode = MCAST_EXCLUDE; pmc->sfcount[MCAST_INCLUDE] = 0; pmc->sfcount[MCAST_EXCLUDE] = 1; + spin_unlock_bh(&pmc->lock); + + for (psf = tomb; psf; psf = nextpsf) { + nextpsf = psf->sf_next; + kfree(psf); + } + for (psf = sources; psf; psf = nextpsf) { + nextpsf = psf->sf_next; + kfree(psf); + } } /* Join a multicast group From 4a6a97e2650c7dd7b1380ba763e9038c814e220c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 12 Jun 2017 16:39:51 -0700 Subject: [PATCH 82/91] netconsole: Remove duplicate "netconsole: " logging prefix It's already added by pr_fmt so remove the explicit use. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/netconsole.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 06ee6395117f..0e27920c2b6b 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -358,7 +358,7 @@ static ssize_t enabled_store(struct config_item *item, if (err) goto out_unlock; - pr_info("netconsole: network logging started\n"); + pr_info("network logging started\n"); } else { /* false */ /* We need to disable the netconsole before cleaning it up * otherwise we might end up in write_msg() with From 665fff2923323e348728e03a7cdb0ce56f316d39 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 12 Jun 2017 17:18:51 -0700 Subject: [PATCH 83/91] net: phy: Fix MDIO_THUNDER dependencies After commit 90eff9096c01 ("net: phy: Allow splitting MDIO bus/device support from PHYs") we could create a configuration where MDIO_DEVICE=y and PHYLIB=m which leads to the following undefined references: drivers/built-in.o: In function `thunder_mdiobus_pci_remove': >> mdio-thunder.c:(.text+0x2a212f): undefined reference to >> `mdiobus_unregister' >> mdio-thunder.c:(.text+0x2a2138): undefined reference to >> `mdiobus_free' drivers/built-in.o: In function `thunder_mdiobus_pci_probe': mdio-thunder.c:(.text+0x2a22e7): undefined reference to `devm_mdiobus_alloc_size' mdio-thunder.c:(.text+0x2a236f): undefined reference to `of_mdiobus_register' Reported-by: kbuild test robot Fixes: 90eff9096c01 ("net: phy: Allow splitting MDIO bus/device support from PHYs") Signed-off-by: Florian Fainelli Tested-by: Randy Dunlap Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index c360dd6ead22..3ab6c58d4be6 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -127,6 +127,7 @@ config MDIO_THUNDER tristate "ThunderX SOCs MDIO buses" depends on 64BIT depends on PCI + depends on !(MDIO_DEVICE=y && PHYLIB=m) select MDIO_CAVIUM help This driver supports the MDIO interfaces found on Cavium From 60cfe1eaccb8af598ebe1bdc44e157ea30fcdd81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 13 Jun 2017 19:10:18 +0200 Subject: [PATCH 84/91] qmi_wwan: new Telewell and Sierra device IDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A new Sierra Wireless EM7305 device ID used in a Toshiba laptop, and two Longcheer device IDs entries used by Telewell TW-3G HSPA+ branded modems. Reported-by: Petr Kloc Reported-by: Teemu Likonen Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 949671ce4039..32a22f4e8356 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -1192,6 +1192,8 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x9056, 8)}, /* Sierra Wireless Modem */ {QMI_FIXED_INTF(0x1199, 0x9057, 8)}, {QMI_FIXED_INTF(0x1199, 0x9061, 8)}, /* Sierra Wireless Modem */ + {QMI_FIXED_INTF(0x1199, 0x9063, 8)}, /* Sierra Wireless EM7305 */ + {QMI_FIXED_INTF(0x1199, 0x9063, 10)}, /* Sierra Wireless EM7305 */ {QMI_FIXED_INTF(0x1199, 0x9071, 8)}, /* Sierra Wireless MC74xx */ {QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx */ {QMI_FIXED_INTF(0x1199, 0x9079, 8)}, /* Sierra Wireless EM74xx */ @@ -1206,6 +1208,8 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */ {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1201, 2)}, /* Telit LE920, LE920A4 */ + {QMI_FIXED_INTF(0x1c9e, 0x9801, 3)}, /* Telewell TW-3G HSPA+ */ + {QMI_FIXED_INTF(0x1c9e, 0x9803, 4)}, /* Telewell TW-3G HSPA+ */ {QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)}, /* XS Stick W100-2 from 4G Systems */ {QMI_FIXED_INTF(0x0b3c, 0xc000, 4)}, /* Olivetti Olicard 100 */ {QMI_FIXED_INTF(0x0b3c, 0xc001, 4)}, /* Olivetti Olicard 120 */ From ace17c369295f088dc8ac8ff468602646fa5cced Mon Sep 17 00:00:00 2001 From: "Tayar, Tomer" Date: Tue, 13 Jun 2017 12:15:59 +0300 Subject: [PATCH 85/91] qed: fix dump of context data Currently when dumping a context data only word number '1' is read for the entire context. Fixes: c965db444629 ("qed: Add support for debug data collection") Signed-off-by: Tomer Tayar Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c index 483241b4b05d..a672f6a860dc 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_debug.c +++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c @@ -2956,7 +2956,7 @@ static u32 qed_grc_dump_ctx_data(struct qed_hwfn *p_hwfn, qed_wr(p_hwfn, p_ptt, s_storm_defs[storm_id].cm_ctx_wr_addr, - BIT(9) | lid); + (i << 9) | lid); *(dump_buf + offset) = qed_rd(p_hwfn, p_ptt, rd_reg_addr); From 20a3d5bf5e5b13c02450ab6178ec374abd830686 Mon Sep 17 00:00:00 2001 From: Mateusz Jurczyk Date: Tue, 13 Jun 2017 20:06:12 +0200 Subject: [PATCH 86/91] caif: Add sockaddr length check before accessing sa_family in connect handler Verify that the caller-provided sockaddr structure is large enough to contain the sa_family field, before accessing it in the connect() handler of the AF_CAIF socket. Since the syscall doesn't enforce a minimum size of the corresponding memory region, very short sockaddrs (zero or one byte long) result in operating on uninitialized memory while referencing sa_family. Signed-off-by: Mateusz Jurczyk Signed-off-by: David S. Miller --- net/caif/caif_socket.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index adcad344c843..21f18ea2fce4 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -754,6 +754,10 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, lock_sock(sk); + err = -EINVAL; + if (addr_len < offsetofend(struct sockaddr, sa_family)) + goto out; + err = -EAFNOSUPPORT; if (uaddr->sa_family != AF_CAIF) goto out; From 74030603dfd9f76c0f279f19f1dd1ee3028fee7a Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Tue, 13 Jun 2017 13:36:24 -0700 Subject: [PATCH 87/91] net_sched: move tcf_lock down after gen_replace_estimator() Laura reported a sleep-in-atomic kernel warning inside tcf_act_police_init() which calls gen_replace_estimator() with spinlock protection. It is not necessary in this case, we already have RTNL lock here so it is enough to protect concurrent writers. For the reader, i.e. tcf_act_police(), it needs to make decision based on this rate estimator, in the worst case we drop more/less packets than necessary while changing the rate in parallel, it is still acceptable. Reported-by: Laura Abbott Reported-by: Nick Huber Cc: Jamal Hadi Salim Signed-off-by: Cong Wang Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/sched/act_police.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/net/sched/act_police.c b/net/sched/act_police.c index f42008b29311..b062bc80c7cb 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -132,21 +132,21 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla, } } - spin_lock_bh(&police->tcf_lock); if (est) { err = gen_replace_estimator(&police->tcf_bstats, NULL, &police->tcf_rate_est, &police->tcf_lock, NULL, est); if (err) - goto failure_unlock; + goto failure; } else if (tb[TCA_POLICE_AVRATE] && (ret == ACT_P_CREATED || !gen_estimator_active(&police->tcf_rate_est))) { err = -EINVAL; - goto failure_unlock; + goto failure; } + spin_lock_bh(&police->tcf_lock); /* No failure allowed after this point */ police->tcfp_mtu = parm->mtu; if (police->tcfp_mtu == 0) { @@ -192,8 +192,6 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla, return ret; -failure_unlock: - spin_unlock_bh(&police->tcf_lock); failure: qdisc_put_rtab(P_tab); qdisc_put_rtab(R_tab); From db46a0e1be7eac45d0bb1bdcd438b8d47c920451 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 14 Jun 2017 16:15:24 +0900 Subject: [PATCH 88/91] net: update undefined ->ndo_change_mtu() comment Update ->ndo_change_mtu() callback comment to remove text about returning error in case of undefined callback. This change makes the comment match the existing code behavior. Signed-off-by: Magnus Damm Signed-off-by: David S. Miller --- include/linux/netdevice.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 846193dfb0ac..4ed952c17fc7 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -914,8 +914,7 @@ struct xfrmdev_ops { * * int (*ndo_change_mtu)(struct net_device *dev, int new_mtu); * Called when a user wants to change the Maximum Transfer Unit - * of a device. If not defined, any request to change MTU will - * will return an error. + * of a device. * * void (*ndo_tx_timeout)(struct net_device *dev); * Callback used when the transmitter has not made any progress From c4f65b09b459c6f0ec27b1a1a65302f7fea5c96f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 14 Jun 2017 13:29:31 +0300 Subject: [PATCH 89/91] net/act_pedit: fix an error code I'm reviewing static checker warnings where we do ERR_PTR(0), which is the same as NULL. I'm pretty sure we intended to return ERR_PTR(-EINVAL) here. Sometimes these bugs lead to a NULL dereference but I don't immediately see that problem here. Fixes: 71d0ed7079df ("net/act_pedit: Support using offset relative to the conventional network headers") Signed-off-by: Dan Carpenter Acked-by: Amir Vadai Signed-off-by: David S. Miller --- net/sched/act_pedit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 164b5ac094be..7dc5892671c8 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -94,8 +94,10 @@ static struct tcf_pedit_key_ex *tcf_pedit_keys_ex_parse(struct nlattr *nla, k++; } - if (n) + if (n) { + err = -EINVAL; goto err_out; + } return keys_ex; From 849a44de91636c24cea799cb8ad8c36433feb913 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Wed, 14 Jun 2017 13:27:37 +0200 Subject: [PATCH 90/91] net: don't global ICMP rate limit packets originating from loopback Florian Weimer seems to have a glibc test-case which requires that loopback interfaces does not get ICMP ratelimited. This was broken by commit c0303efeab73 ("net: reduce cycles spend on ICMP replies that gets rate limited"). An ICMP response will usually be routed back-out the same incoming interface. Thus, take advantage of this and skip global ICMP ratelimit when the incoming device is loopback. In the unlikely event that the outgoing it not loopback, due to strange routing policy rules, ICMP rate limiting still works via peer ratelimiting via icmpv4_xrlim_allow(). Thus, we should still comply with RFC1812 (section 4.3.2.8 "Rate Limiting"). This seems to fix the reproducer given by Florian. While still avoiding to perform expensive and unneeded outgoing route lookup for rate limited packets (in the non-loopback case). Fixes: c0303efeab73 ("net: reduce cycles spend on ICMP replies that gets rate limited") Reported-by: Florian Weimer Reported-by: "H.J. Lu" Signed-off-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- net/ipv4/icmp.c | 8 ++++++-- net/ipv6/icmp.c | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 43318b5f5647..9144fa7df2ad 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -657,8 +657,12 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) /* Needed by both icmp_global_allow and icmp_xmit_lock */ local_bh_disable(); - /* Check global sysctl_icmp_msgs_per_sec ratelimit */ - if (!icmpv4_global_allow(net, type, code)) + /* Check global sysctl_icmp_msgs_per_sec ratelimit, unless + * incoming dev is loopback. If outgoing dev change to not be + * loopback, then peer ratelimit still work (in icmpv4_xrlim_allow) + */ + if (!(skb_in->dev && (skb_in->dev->flags&IFF_LOOPBACK)) && + !icmpv4_global_allow(net, type, code)) goto out_bh_enable; sk = icmp_xmit_lock(net); diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 230b5aac9f03..8d7b113958b1 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -491,7 +491,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, local_bh_disable(); /* Check global sysctl_icmp_msgs_per_sec ratelimit */ - if (!icmpv6_global_allow(type)) + if (!(skb->dev->flags&IFF_LOOPBACK) && !icmpv6_global_allow(type)) goto out_bh_enable; mip6_addr_swap(skb); From 640f93cc6ea7327588be3cc0849d1342aac0393a Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Wed, 14 Jun 2017 16:35:31 -0700 Subject: [PATCH 91/91] i40e: Fix a sleep-in-atomic bug The driver may sleep under a spin lock, and the function call path is: i40e_ndo_set_vf_port_vlan (acquire the lock by spin_lock_bh) i40e_vsi_remove_pvid i40e_vlan_stripping_disable i40e_aq_update_vsi_params i40e_asq_send_command mutex_lock --> may sleep To fixed it, the spin lock is released before "i40e_vsi_remove_pvid", and the lock is acquired again after this function. Signed-off-by: Jia-Ju Bai Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 95c23fbaa211..0fb38ca78900 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -3017,10 +3017,12 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id, VLAN_VID_MASK)); } + spin_unlock_bh(&vsi->mac_filter_hash_lock); if (vlan_id || qos) ret = i40e_vsi_add_pvid(vsi, vlanprio); else i40e_vsi_remove_pvid(vsi); + spin_lock_bh(&vsi->mac_filter_hash_lock); if (vlan_id) { dev_info(&pf->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n",