commit: b2dfe994a979d5ace0f18e467c1e82bfa4d3ab30 Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Sat Mar 31 22:19:50 2018 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Sat Mar 31 22:19:50 2018 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=b2dfe994
Linux patch 4.15.15 0000_README | 4 + 1014_linux-4.15.15.patch | 1683 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1687 insertions(+) diff --git a/0000_README b/0000_README index f4d8a80..f1a4ce6 100644 --- a/0000_README +++ b/0000_README @@ -99,6 +99,10 @@ Patch: 1013_linux-4.15.14.patch From: http://www.kernel.org Desc: Linux 4.15.14 +Patch: 1014_linux-4.15.15.patch +From: http://www.kernel.org +Desc: Linux 4.15.15 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1014_linux-4.15.15.patch b/1014_linux-4.15.15.patch new file mode 100644 index 0000000..ab1089f --- /dev/null +++ b/1014_linux-4.15.15.patch @@ -0,0 +1,1683 @@ +diff --git a/Makefile b/Makefile +index a5e561900daf..20c9b7bfeed4 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 4 + PATCHLEVEL = 15 +-SUBLEVEL = 14 ++SUBLEVEL = 15 + EXTRAVERSION = + NAME = Fearless Coyote + +diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c +index 16f9bee992fe..0f6576802607 100644 +--- a/drivers/net/ethernet/arc/emac_rockchip.c ++++ b/drivers/net/ethernet/arc/emac_rockchip.c +@@ -169,8 +169,10 @@ static int emac_rockchip_probe(struct platform_device *pdev) + /* Optional regulator for PHY */ + priv->regulator = devm_regulator_get_optional(dev, "phy"); + if (IS_ERR(priv->regulator)) { +- if (PTR_ERR(priv->regulator) == -EPROBE_DEFER) +- return -EPROBE_DEFER; ++ if (PTR_ERR(priv->regulator) == -EPROBE_DEFER) { ++ err = -EPROBE_DEFER; ++ goto out_clk_disable; ++ } + dev_err(dev, "no regulator found\n"); + priv->regulator = NULL; + } +diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c +index 087f01b4dc3a..f239ef2e6f23 100644 +--- a/drivers/net/ethernet/broadcom/bcmsysport.c ++++ b/drivers/net/ethernet/broadcom/bcmsysport.c +@@ -855,10 +855,12 @@ static void bcm_sysport_tx_reclaim_one(struct bcm_sysport_tx_ring *ring, + static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv, + struct bcm_sysport_tx_ring *ring) + { +- unsigned int c_index, last_c_index, last_tx_cn, num_tx_cbs; + unsigned int pkts_compl = 0, bytes_compl = 0; + struct net_device *ndev = priv->netdev; ++ unsigned int txbds_processed = 0; + struct bcm_sysport_cb *cb; ++ unsigned int txbds_ready; ++ unsigned int c_index; + u32 hw_ind; + + /* Clear status before servicing to reduce spurious interrupts */ +@@ -871,29 +873,23 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv, + /* Compute how many descriptors have been processed since last call */ + hw_ind = tdma_readl(priv, TDMA_DESC_RING_PROD_CONS_INDEX(ring->index)); + c_index = (hw_ind >> RING_CONS_INDEX_SHIFT) & RING_CONS_INDEX_MASK; +- ring->p_index = (hw_ind & RING_PROD_INDEX_MASK); +- +- last_c_index = ring->c_index; +- num_tx_cbs = ring->size; +- +- c_index &= (num_tx_cbs - 1); +- +- if (c_index >= last_c_index) +- last_tx_cn = c_index - last_c_index; +- else +- last_tx_cn = num_tx_cbs - last_c_index + c_index; ++ txbds_ready = (c_index - ring->c_index) & RING_CONS_INDEX_MASK; + + netif_dbg(priv, tx_done, ndev, +- "ring=%d c_index=%d last_tx_cn=%d last_c_index=%d\n", +- ring->index, c_index, last_tx_cn, last_c_index); ++ "ring=%d old_c_index=%u c_index=%u txbds_ready=%u\n", ++ ring->index, ring->c_index, c_index, txbds_ready); + +- while (last_tx_cn-- > 0) { +- cb = ring->cbs + last_c_index; ++ while (txbds_processed < txbds_ready) { ++ cb = &ring->cbs[ring->clean_index]; + bcm_sysport_tx_reclaim_one(ring, cb, &bytes_compl, &pkts_compl); + + ring->desc_count++; +- last_c_index++; +- last_c_index &= (num_tx_cbs - 1); ++ txbds_processed++; ++ ++ if (likely(ring->clean_index < ring->size - 1)) ++ ring->clean_index++; ++ else ++ ring->clean_index = 0; + } + + u64_stats_update_begin(&priv->syncp); +@@ -1406,6 +1402,7 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv, + netif_tx_napi_add(priv->netdev, &ring->napi, bcm_sysport_tx_poll, 64); + ring->index = index; + ring->size = size; ++ ring->clean_index = 0; + ring->alloc_size = ring->size; + ring->desc_cpu = p; + ring->desc_count = ring->size; +diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h +index f5a984c1c986..19c91c76e327 100644 +--- a/drivers/net/ethernet/broadcom/bcmsysport.h ++++ b/drivers/net/ethernet/broadcom/bcmsysport.h +@@ -706,7 +706,7 @@ struct bcm_sysport_tx_ring { + unsigned int desc_count; /* Number of descriptors */ + unsigned int curr_desc; /* Current descriptor */ + unsigned int c_index; /* Last consumer index */ +- unsigned int p_index; /* Current producer index */ ++ unsigned int clean_index; /* Current clean index */ + struct bcm_sysport_cb *cbs; /* Transmit control blocks */ + struct dma_desc *desc_cpu; /* CPU view of the descriptor */ + struct bcm_sysport_priv *priv; /* private context backpointer */ +diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +index 7caa8da48421..e4ec32a9ca15 100644 +--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c ++++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +@@ -2008,7 +2008,6 @@ static inline int dpaa_xmit(struct dpaa_priv *priv, + } + + if (unlikely(err < 0)) { +- percpu_stats->tx_errors++; + percpu_stats->tx_fifo_errors++; + return err; + } +@@ -2278,7 +2277,6 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal, + vaddr = phys_to_virt(addr); + prefetch(vaddr + qm_fd_get_offset(fd)); + +- fd_format = qm_fd_get_format(fd); + /* The only FD types that we may receive are contig and S/G */ + WARN_ON((fd_format != qm_fd_contig) && (fd_format != qm_fd_sg)); + +@@ -2311,8 +2309,10 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal, + + skb_len = skb->len; + +- if (unlikely(netif_receive_skb(skb) == NET_RX_DROP)) ++ if (unlikely(netif_receive_skb(skb) == NET_RX_DROP)) { ++ percpu_stats->rx_dropped++; + return qman_cb_dqrr_consume; ++ } + + percpu_stats->rx_packets++; + percpu_stats->rx_bytes += skb_len; +@@ -2860,7 +2860,7 @@ static int dpaa_remove(struct platform_device *pdev) + struct device *dev; + int err; + +- dev = &pdev->dev; ++ dev = pdev->dev.parent; + net_dev = dev_get_drvdata(dev); + + priv = netdev_priv(net_dev); +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index a74300a4459c..febadd39e29a 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -3578,6 +3578,8 @@ fec_drv_remove(struct platform_device *pdev) + fec_enet_mii_remove(fep); + if (fep->reg_phy) + regulator_disable(fep->reg_phy); ++ pm_runtime_put(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); + if (of_phy_is_fixed_link(np)) + of_phy_deregister_fixed_link(np); + of_node_put(fep->phy_node); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +index 93728c694e6d..0a9adc5962fb 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +@@ -385,13 +385,13 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_egress[] = { + + static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = { + MLXSW_SP_CPU_PORT_SB_CM, ++ MLXSW_SP_SB_CM(MLXSW_PORT_MAX_MTU, 0, 0), ++ MLXSW_SP_SB_CM(MLXSW_PORT_MAX_MTU, 0, 0), ++ MLXSW_SP_SB_CM(MLXSW_PORT_MAX_MTU, 0, 0), ++ MLXSW_SP_SB_CM(MLXSW_PORT_MAX_MTU, 0, 0), ++ MLXSW_SP_SB_CM(MLXSW_PORT_MAX_MTU, 0, 0), + MLXSW_SP_CPU_PORT_SB_CM, +- MLXSW_SP_CPU_PORT_SB_CM, +- MLXSW_SP_CPU_PORT_SB_CM, +- MLXSW_SP_CPU_PORT_SB_CM, +- MLXSW_SP_CPU_PORT_SB_CM, +- MLXSW_SP_CPU_PORT_SB_CM, +- MLXSW_SP_SB_CM(10000, 0, 0), ++ MLXSW_SP_SB_CM(MLXSW_PORT_MAX_MTU, 0, 0), + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, +diff --git a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c +index 409041eab189..fba7f5c34b85 100644 +--- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c ++++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c +@@ -1681,6 +1681,13 @@ qed_iwarp_parse_rx_pkt(struct qed_hwfn *p_hwfn, + iph = (struct iphdr *)((u8 *)(ethh) + eth_hlen); + + if (eth_type == ETH_P_IP) { ++ if (iph->protocol != IPPROTO_TCP) { ++ DP_NOTICE(p_hwfn, ++ "Unexpected ip protocol on ll2 %x\n", ++ iph->protocol); ++ return -EINVAL; ++ } ++ + cm_info->local_ip[0] = ntohl(iph->daddr); + cm_info->remote_ip[0] = ntohl(iph->saddr); + cm_info->ip_version = TCP_IPV4; +@@ -1689,6 +1696,14 @@ qed_iwarp_parse_rx_pkt(struct qed_hwfn *p_hwfn, + *payload_len = ntohs(iph->tot_len) - ip_hlen; + } else if (eth_type == ETH_P_IPV6) { + ip6h = (struct ipv6hdr *)iph; ++ ++ if (ip6h->nexthdr != IPPROTO_TCP) { ++ DP_NOTICE(p_hwfn, ++ "Unexpected ip protocol on ll2 %x\n", ++ iph->protocol); ++ return -EINVAL; ++ } ++ + for (i = 0; i < 4; i++) { + cm_info->local_ip[i] = + ntohl(ip6h->daddr.in6_u.u6_addr32[i]); +@@ -1906,8 +1921,8 @@ qed_iwarp_update_fpdu_length(struct qed_hwfn *p_hwfn, + /* Missing lower byte is now available */ + mpa_len = fpdu->fpdu_length | *mpa_data; + fpdu->fpdu_length = QED_IWARP_FPDU_LEN_WITH_PAD(mpa_len); +- fpdu->mpa_frag_len = fpdu->fpdu_length; + /* one byte of hdr */ ++ fpdu->mpa_frag_len = 1; + fpdu->incomplete_bytes = fpdu->fpdu_length - 1; + DP_VERBOSE(p_hwfn, + QED_MSG_RDMA, +diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c +index 8f9b3eb82137..cdcccecfc24a 100644 +--- a/drivers/net/ethernet/qlogic/qede/qede_main.c ++++ b/drivers/net/ethernet/qlogic/qede/qede_main.c +@@ -2066,8 +2066,6 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode, + link_params.link_up = true; + edev->ops->common->set_link(edev->cdev, &link_params); + +- qede_rdma_dev_event_open(edev); +- + edev->state = QEDE_STATE_OPEN; + + DP_INFO(edev, "Ending successfully qede load\n"); +@@ -2168,12 +2166,14 @@ static void qede_link_update(void *dev, struct qed_link_output *link) + DP_NOTICE(edev, "Link is up\n"); + netif_tx_start_all_queues(edev->ndev); + netif_carrier_on(edev->ndev); ++ qede_rdma_dev_event_open(edev); + } + } else { + if (netif_carrier_ok(edev->ndev)) { + DP_NOTICE(edev, "Link is down\n"); + netif_tx_disable(edev->ndev); + netif_carrier_off(edev->ndev); ++ qede_rdma_dev_event_close(edev); + } + } + } +diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c +index a1ffc3ed77f9..c08d74cd1fd2 100644 +--- a/drivers/net/ethernet/ti/cpsw.c ++++ b/drivers/net/ethernet/ti/cpsw.c +@@ -996,7 +996,8 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave, + /* set speed_in input in case RMII mode is used in 100Mbps */ + if (phy->speed == 100) + mac_control |= BIT(15); +- else if (phy->speed == 10) ++ /* in band mode only works in 10Mbps RGMII mode */ ++ else if ((phy->speed == 10) && phy_interface_is_rgmii(phy)) + mac_control |= BIT(18); /* In Band mode */ + + if (priv->rx_pause) +diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c +index a0f2be81d52e..4884f6149b0a 100644 +--- a/drivers/net/macvlan.c ++++ b/drivers/net/macvlan.c +@@ -1036,7 +1036,7 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev, + lowerdev_features &= (features | ~NETIF_F_LRO); + features = netdev_increment_features(lowerdev_features, features, mask); + features |= ALWAYS_ON_FEATURES; +- features &= ~NETIF_F_NETNS_LOCAL; ++ features &= (ALWAYS_ON_FEATURES | MACVLAN_FEATURES); + + return features; + } +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index 39de77a8bb63..dba6d17ad885 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -614,6 +614,91 @@ static void phy_error(struct phy_device *phydev) + phy_trigger_machine(phydev, false); + } + ++/** ++ * phy_disable_interrupts - Disable the PHY interrupts from the PHY side ++ * @phydev: target phy_device struct ++ */ ++static int phy_disable_interrupts(struct phy_device *phydev) ++{ ++ int err; ++ ++ /* Disable PHY interrupts */ ++ err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED); ++ if (err) ++ goto phy_err; ++ ++ /* Clear the interrupt */ ++ err = phy_clear_interrupt(phydev); ++ if (err) ++ goto phy_err; ++ ++ return 0; ++ ++phy_err: ++ phy_error(phydev); ++ ++ return err; ++} ++ ++/** ++ * phy_change - Called by the phy_interrupt to handle PHY changes ++ * @phydev: phy_device struct that interrupted ++ */ ++static irqreturn_t phy_change(struct phy_device *phydev) ++{ ++ if (phy_interrupt_is_valid(phydev)) { ++ if (phydev->drv->did_interrupt && ++ !phydev->drv->did_interrupt(phydev)) ++ goto ignore; ++ ++ if (phy_disable_interrupts(phydev)) ++ goto phy_err; ++ } ++ ++ mutex_lock(&phydev->lock); ++ if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state)) ++ phydev->state = PHY_CHANGELINK; ++ mutex_unlock(&phydev->lock); ++ ++ if (phy_interrupt_is_valid(phydev)) { ++ atomic_dec(&phydev->irq_disable); ++ enable_irq(phydev->irq); ++ ++ /* Reenable interrupts */ ++ if (PHY_HALTED != phydev->state && ++ phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED)) ++ goto irq_enable_err; ++ } ++ ++ /* reschedule state queue work to run as soon as possible */ ++ phy_trigger_machine(phydev, true); ++ return IRQ_HANDLED; ++ ++ignore: ++ atomic_dec(&phydev->irq_disable); ++ enable_irq(phydev->irq); ++ return IRQ_NONE; ++ ++irq_enable_err: ++ disable_irq(phydev->irq); ++ atomic_inc(&phydev->irq_disable); ++phy_err: ++ phy_error(phydev); ++ return IRQ_NONE; ++} ++ ++/** ++ * phy_change_work - Scheduled by the phy_mac_interrupt to handle PHY changes ++ * @work: work_struct that describes the work to be done ++ */ ++void phy_change_work(struct work_struct *work) ++{ ++ struct phy_device *phydev = ++ container_of(work, struct phy_device, phy_queue); ++ ++ phy_change(phydev); ++} ++ + /** + * phy_interrupt - PHY interrupt handler + * @irq: interrupt line +@@ -632,9 +717,7 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat) + disable_irq_nosync(irq); + atomic_inc(&phydev->irq_disable); + +- phy_change(phydev); +- +- return IRQ_HANDLED; ++ return phy_change(phydev); + } + + /** +@@ -651,32 +734,6 @@ static int phy_enable_interrupts(struct phy_device *phydev) + return phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); + } + +-/** +- * phy_disable_interrupts - Disable the PHY interrupts from the PHY side +- * @phydev: target phy_device struct +- */ +-static int phy_disable_interrupts(struct phy_device *phydev) +-{ +- int err; +- +- /* Disable PHY interrupts */ +- err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED); +- if (err) +- goto phy_err; +- +- /* Clear the interrupt */ +- err = phy_clear_interrupt(phydev); +- if (err) +- goto phy_err; +- +- return 0; +- +-phy_err: +- phy_error(phydev); +- +- return err; +-} +- + /** + * phy_start_interrupts - request and enable interrupts for a PHY device + * @phydev: target phy_device struct +@@ -727,64 +784,6 @@ int phy_stop_interrupts(struct phy_device *phydev) + } + EXPORT_SYMBOL(phy_stop_interrupts); + +-/** +- * phy_change - Called by the phy_interrupt to handle PHY changes +- * @phydev: phy_device struct that interrupted +- */ +-void phy_change(struct phy_device *phydev) +-{ +- if (phy_interrupt_is_valid(phydev)) { +- if (phydev->drv->did_interrupt && +- !phydev->drv->did_interrupt(phydev)) +- goto ignore; +- +- if (phy_disable_interrupts(phydev)) +- goto phy_err; +- } +- +- mutex_lock(&phydev->lock); +- if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state)) +- phydev->state = PHY_CHANGELINK; +- mutex_unlock(&phydev->lock); +- +- if (phy_interrupt_is_valid(phydev)) { +- atomic_dec(&phydev->irq_disable); +- enable_irq(phydev->irq); +- +- /* Reenable interrupts */ +- if (PHY_HALTED != phydev->state && +- phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED)) +- goto irq_enable_err; +- } +- +- /* reschedule state queue work to run as soon as possible */ +- phy_trigger_machine(phydev, true); +- return; +- +-ignore: +- atomic_dec(&phydev->irq_disable); +- enable_irq(phydev->irq); +- return; +- +-irq_enable_err: +- disable_irq(phydev->irq); +- atomic_inc(&phydev->irq_disable); +-phy_err: +- phy_error(phydev); +-} +- +-/** +- * phy_change_work - Scheduled by the phy_mac_interrupt to handle PHY changes +- * @work: work_struct that describes the work to be done +- */ +-void phy_change_work(struct work_struct *work) +-{ +- struct phy_device *phydev = +- container_of(work, struct phy_device, phy_queue); +- +- phy_change(phydev); +-} +- + /** + * phy_stop - Bring down the PHY link, and stop checking the status + * @phydev: target phy_device struct +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index d312b314825e..a1e7ea4d4b16 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -999,10 +999,17 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, + err = sysfs_create_link(&phydev->mdio.dev.kobj, &dev->dev.kobj, + "attached_dev"); + if (!err) { +- err = sysfs_create_link(&dev->dev.kobj, &phydev->mdio.dev.kobj, +- "phydev"); +- if (err) +- goto error; ++ err = sysfs_create_link_nowarn(&dev->dev.kobj, ++ &phydev->mdio.dev.kobj, ++ "phydev"); ++ if (err) { ++ dev_err(&dev->dev, "could not add device link to %s err %d\n", ++ kobject_name(&phydev->mdio.dev.kobj), ++ err); ++ /* non-fatal - some net drivers can use one netdevice ++ * with more then one phy ++ */ ++ } + + phydev->sysfs_links = true; + } +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 9f79f9274c50..d37183aec313 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -257,7 +257,7 @@ struct ppp_net { + /* Prototypes. */ + static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, + struct file *file, unsigned int cmd, unsigned long arg); +-static void ppp_xmit_process(struct ppp *ppp); ++static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb); + static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb); + static void ppp_push(struct ppp *ppp); + static void ppp_channel_push(struct channel *pch); +@@ -513,13 +513,12 @@ static ssize_t ppp_write(struct file *file, const char __user *buf, + goto out; + } + +- skb_queue_tail(&pf->xq, skb); +- + switch (pf->kind) { + case INTERFACE: +- ppp_xmit_process(PF_TO_PPP(pf)); ++ ppp_xmit_process(PF_TO_PPP(pf), skb); + break; + case CHANNEL: ++ skb_queue_tail(&pf->xq, skb); + ppp_channel_push(PF_TO_CHANNEL(pf)); + break; + } +@@ -1267,8 +1266,8 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) + put_unaligned_be16(proto, pp); + + skb_scrub_packet(skb, !net_eq(ppp->ppp_net, dev_net(dev))); +- skb_queue_tail(&ppp->file.xq, skb); +- ppp_xmit_process(ppp); ++ ppp_xmit_process(ppp, skb); ++ + return NETDEV_TX_OK; + + outf: +@@ -1420,13 +1419,14 @@ static void ppp_setup(struct net_device *dev) + */ + + /* Called to do any work queued up on the transmit side that can now be done */ +-static void __ppp_xmit_process(struct ppp *ppp) ++static void __ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb) + { +- struct sk_buff *skb; +- + ppp_xmit_lock(ppp); + if (!ppp->closing) { + ppp_push(ppp); ++ ++ if (skb) ++ skb_queue_tail(&ppp->file.xq, skb); + while (!ppp->xmit_pending && + (skb = skb_dequeue(&ppp->file.xq))) + ppp_send_frame(ppp, skb); +@@ -1440,7 +1440,7 @@ static void __ppp_xmit_process(struct ppp *ppp) + ppp_xmit_unlock(ppp); + } + +-static void ppp_xmit_process(struct ppp *ppp) ++static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb) + { + local_bh_disable(); + +@@ -1448,7 +1448,7 @@ static void ppp_xmit_process(struct ppp *ppp) + goto err; + + (*this_cpu_ptr(ppp->xmit_recursion))++; +- __ppp_xmit_process(ppp); ++ __ppp_xmit_process(ppp, skb); + (*this_cpu_ptr(ppp->xmit_recursion))--; + + local_bh_enable(); +@@ -1458,6 +1458,8 @@ static void ppp_xmit_process(struct ppp *ppp) + err: + local_bh_enable(); + ++ kfree_skb(skb); ++ + if (net_ratelimit()) + netdev_err(ppp->dev, "recursion detected\n"); + } +@@ -1942,7 +1944,7 @@ static void __ppp_channel_push(struct channel *pch) + if (skb_queue_empty(&pch->file.xq)) { + ppp = pch->ppp; + if (ppp) +- __ppp_xmit_process(ppp); ++ __ppp_xmit_process(ppp, NULL); + } + } + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index a468439969df..56c701b73c12 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -2395,7 +2395,7 @@ static int team_nl_send_options_get(struct team *team, u32 portid, u32 seq, + if (!nlh) { + err = __send_and_alloc_skb(&skb, team, portid, send_func); + if (err) +- goto errout; ++ return err; + goto send_done; + } + +@@ -2681,7 +2681,7 @@ static int team_nl_send_port_list_get(struct team *team, u32 portid, u32 seq, + if (!nlh) { + err = __send_and_alloc_skb(&skb, team, portid, send_func); + if (err) +- goto errout; ++ return err; + goto send_done; + } + +diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c +index 61e9d0bca197..eeabbcf7a4e2 100644 +--- a/drivers/s390/net/qeth_core_main.c ++++ b/drivers/s390/net/qeth_core_main.c +@@ -526,8 +526,7 @@ static inline int qeth_is_cq(struct qeth_card *card, unsigned int queue) + queue == card->qdio.no_in_queues - 1; + } + +- +-static int qeth_issue_next_read(struct qeth_card *card) ++static int __qeth_issue_next_read(struct qeth_card *card) + { + int rc; + struct qeth_cmd_buffer *iob; +@@ -558,6 +557,17 @@ static int qeth_issue_next_read(struct qeth_card *card) + return rc; + } + ++static int qeth_issue_next_read(struct qeth_card *card) ++{ ++ int ret; ++ ++ spin_lock_irq(get_ccwdev_lock(CARD_RDEV(card))); ++ ret = __qeth_issue_next_read(card); ++ spin_unlock_irq(get_ccwdev_lock(CARD_RDEV(card))); ++ ++ return ret; ++} ++ + static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card) + { + struct qeth_reply *reply; +@@ -961,7 +971,7 @@ void qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread) + spin_lock_irqsave(&card->thread_mask_lock, flags); + card->thread_running_mask &= ~thread; + spin_unlock_irqrestore(&card->thread_mask_lock, flags); +- wake_up(&card->wait_q); ++ wake_up_all(&card->wait_q); + } + EXPORT_SYMBOL_GPL(qeth_clear_thread_running_bit); + +@@ -1165,6 +1175,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, + } + rc = qeth_get_problem(cdev, irb); + if (rc) { ++ card->read_or_write_problem = 1; + qeth_clear_ipacmd_list(card); + qeth_schedule_recovery(card); + goto out; +@@ -1183,7 +1194,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, + return; + if (channel == &card->read && + channel->state == CH_STATE_UP) +- qeth_issue_next_read(card); ++ __qeth_issue_next_read(card); + + iob = channel->iob; + index = channel->buf_no; +@@ -5022,8 +5033,6 @@ static void qeth_core_free_card(struct qeth_card *card) + QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); + qeth_clean_channel(&card->read); + qeth_clean_channel(&card->write); +- if (card->dev) +- free_netdev(card->dev); + qeth_free_qdio_buffers(card); + unregister_service_level(&card->qeth_service_level); + kfree(card); +diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c +index 5863ea170ff2..42d56b3bed82 100644 +--- a/drivers/s390/net/qeth_l2_main.c ++++ b/drivers/s390/net/qeth_l2_main.c +@@ -933,8 +933,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) + qeth_l2_set_offline(cgdev); + + if (card->dev) { +- netif_napi_del(&card->napi); + unregister_netdev(card->dev); ++ free_netdev(card->dev); + card->dev = NULL; + } + return; +diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c +index 33131c594627..5287eab5c600 100644 +--- a/drivers/s390/net/qeth_l3_main.c ++++ b/drivers/s390/net/qeth_l3_main.c +@@ -3042,8 +3042,8 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) + qeth_l3_set_offline(cgdev); + + if (card->dev) { +- netif_napi_del(&card->napi); + unregister_netdev(card->dev); ++ free_netdev(card->dev); + card->dev = NULL; + } + +diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c +index e4f5bb056fd2..ba3cfa8e279b 100644 +--- a/drivers/soc/fsl/qbman/qman.c ++++ b/drivers/soc/fsl/qbman/qman.c +@@ -2443,39 +2443,21 @@ struct cgr_comp { + struct completion completion; + }; + +-static int qman_delete_cgr_thread(void *p) ++static void qman_delete_cgr_smp_call(void *p) + { +- struct cgr_comp *cgr_comp = (struct cgr_comp *)p; +- int ret; +- +- ret = qman_delete_cgr(cgr_comp->cgr); +- complete(&cgr_comp->completion); +- +- return ret; ++ qman_delete_cgr((struct qman_cgr *)p); + } + + void qman_delete_cgr_safe(struct qman_cgr *cgr) + { +- struct task_struct *thread; +- struct cgr_comp cgr_comp; +- + preempt_disable(); + if (qman_cgr_cpus[cgr->cgrid] != smp_processor_id()) { +- init_completion(&cgr_comp.completion); +- cgr_comp.cgr = cgr; +- thread = kthread_create(qman_delete_cgr_thread, &cgr_comp, +- "cgr_del"); +- +- if (IS_ERR(thread)) +- goto out; +- +- kthread_bind(thread, qman_cgr_cpus[cgr->cgrid]); +- wake_up_process(thread); +- wait_for_completion(&cgr_comp.completion); ++ smp_call_function_single(qman_cgr_cpus[cgr->cgrid], ++ qman_delete_cgr_smp_call, cgr, true); + preempt_enable(); + return; + } +-out: ++ + qman_delete_cgr(cgr); + preempt_enable(); + } +diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c +index aecb15f84557..808f018fa976 100644 +--- a/fs/sysfs/symlink.c ++++ b/fs/sysfs/symlink.c +@@ -107,6 +107,7 @@ int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target, + { + return sysfs_do_create_link(kobj, target, name, 0); + } ++EXPORT_SYMBOL_GPL(sysfs_create_link_nowarn); + + /** + * sysfs_delete_link - remove symlink in object's directory. +diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h +index 8b7fd8eeccee..cb8a9ce149de 100644 +--- a/include/linux/cgroup-defs.h ++++ b/include/linux/cgroup-defs.h +@@ -755,13 +755,13 @@ struct sock_cgroup_data { + * updaters and return part of the previous pointer as the prioidx or + * classid. Such races are short-lived and the result isn't critical. + */ +-static inline u16 sock_cgroup_prioidx(struct sock_cgroup_data *skcd) ++static inline u16 sock_cgroup_prioidx(const struct sock_cgroup_data *skcd) + { + /* fallback to 1 which is always the ID of the root cgroup */ + return (skcd->is_data & 1) ? skcd->prioidx : 1; + } + +-static inline u32 sock_cgroup_classid(struct sock_cgroup_data *skcd) ++static inline u32 sock_cgroup_classid(const struct sock_cgroup_data *skcd) + { + /* fallback to 0 which is the unconfigured default classid */ + return (skcd->is_data & 1) ? skcd->classid : 0; +diff --git a/include/linux/phy.h b/include/linux/phy.h +index 123cd703741d..ea0cbd6d9556 100644 +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -897,7 +897,6 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner); + int phy_drivers_register(struct phy_driver *new_driver, int n, + struct module *owner); + void phy_state_machine(struct work_struct *work); +-void phy_change(struct phy_device *phydev); + void phy_change_work(struct work_struct *work); + void phy_mac_interrupt(struct phy_device *phydev, int new_link); + void phy_start_machine(struct phy_device *phydev); +diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h +index 361c08e35dbc..7fd514f36e74 100644 +--- a/include/linux/rhashtable.h ++++ b/include/linux/rhashtable.h +@@ -750,8 +750,10 @@ static inline void *__rhashtable_insert_fast( + if (!key || + (params.obj_cmpfn ? + params.obj_cmpfn(&arg, rht_obj(ht, head)) : +- rhashtable_compare(&arg, rht_obj(ht, head)))) ++ rhashtable_compare(&arg, rht_obj(ht, head)))) { ++ pprev = &head->next; + continue; ++ } + + data = rht_obj(ht, head); + +diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h +index d6ec5a5a6782..d794aebb3157 100644 +--- a/include/net/sch_generic.h ++++ b/include/net/sch_generic.h +@@ -735,6 +735,16 @@ static inline void __qdisc_drop(struct sk_buff *skb, struct sk_buff **to_free) + *to_free = skb; + } + ++static inline void __qdisc_drop_all(struct sk_buff *skb, ++ struct sk_buff **to_free) ++{ ++ if (skb->prev) ++ skb->prev->next = *to_free; ++ else ++ skb->next = *to_free; ++ *to_free = skb; ++} ++ + static inline unsigned int __qdisc_queue_drop_head(struct Qdisc *sch, + struct qdisc_skb_head *qh, + struct sk_buff **to_free) +@@ -855,6 +865,15 @@ static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch, + return NET_XMIT_DROP; + } + ++static inline int qdisc_drop_all(struct sk_buff *skb, struct Qdisc *sch, ++ struct sk_buff **to_free) ++{ ++ __qdisc_drop_all(skb, to_free); ++ qdisc_qstats_drop(sch); ++ ++ return NET_XMIT_DROP; ++} ++ + /* Length to Time (L2T) lookup in a qdisc_rate_table, to determine how + long it will take to send a packet given its size. + */ +diff --git a/lib/rhashtable.c b/lib/rhashtable.c +index ddd7dde87c3c..b734ce731a7a 100644 +--- a/lib/rhashtable.c ++++ b/lib/rhashtable.c +@@ -537,8 +537,10 @@ static void *rhashtable_lookup_one(struct rhashtable *ht, + if (!key || + (ht->p.obj_cmpfn ? + ht->p.obj_cmpfn(&arg, rht_obj(ht, head)) : +- rhashtable_compare(&arg, rht_obj(ht, head)))) ++ rhashtable_compare(&arg, rht_obj(ht, head)))) { ++ pprev = &head->next; + continue; ++ } + + if (!ht->rhlist) + return rht_obj(ht, head); +diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c +index 8e83cbdc049c..6f2e3dc44a80 100644 +--- a/lib/test_rhashtable.c ++++ b/lib/test_rhashtable.c +@@ -79,6 +79,21 @@ struct thread_data { + struct test_obj *objs; + }; + ++static u32 my_hashfn(const void *data, u32 len, u32 seed) ++{ ++ const struct test_obj_rhl *obj = data; ++ ++ return (obj->value.id % 10) << RHT_HASH_RESERVED_SPACE; ++} ++ ++static int my_cmpfn(struct rhashtable_compare_arg *arg, const void *obj) ++{ ++ const struct test_obj_rhl *test_obj = obj; ++ const struct test_obj_val *val = arg->key; ++ ++ return test_obj->value.id - val->id; ++} ++ + static struct rhashtable_params test_rht_params = { + .head_offset = offsetof(struct test_obj, node), + .key_offset = offsetof(struct test_obj, value), +@@ -87,6 +102,17 @@ static struct rhashtable_params test_rht_params = { + .nulls_base = (3U << RHT_BASE_SHIFT), + }; + ++static struct rhashtable_params test_rht_params_dup = { ++ .head_offset = offsetof(struct test_obj_rhl, list_node), ++ .key_offset = offsetof(struct test_obj_rhl, value), ++ .key_len = sizeof(struct test_obj_val), ++ .hashfn = jhash, ++ .obj_hashfn = my_hashfn, ++ .obj_cmpfn = my_cmpfn, ++ .nelem_hint = 128, ++ .automatic_shrinking = false, ++}; ++ + static struct semaphore prestart_sem; + static struct semaphore startup_sem = __SEMAPHORE_INITIALIZER(startup_sem, 0); + +@@ -469,6 +495,112 @@ static int __init test_rhashtable_max(struct test_obj *array, + return err; + } + ++static unsigned int __init print_ht(struct rhltable *rhlt) ++{ ++ struct rhashtable *ht; ++ const struct bucket_table *tbl; ++ char buff[512] = ""; ++ unsigned int i, cnt = 0; ++ ++ ht = &rhlt->ht; ++ tbl = rht_dereference(ht->tbl, ht); ++ for (i = 0; i < tbl->size; i++) { ++ struct rhash_head *pos, *next; ++ struct test_obj_rhl *p; ++ ++ pos = rht_dereference(tbl->buckets[i], ht); ++ next = !rht_is_a_nulls(pos) ? rht_dereference(pos->next, ht) : NULL; ++ ++ if (!rht_is_a_nulls(pos)) { ++ sprintf(buff, "%s\nbucket[%d] -> ", buff, i); ++ } ++ ++ while (!rht_is_a_nulls(pos)) { ++ struct rhlist_head *list = container_of(pos, struct rhlist_head, rhead); ++ sprintf(buff, "%s[[", buff); ++ do { ++ pos = &list->rhead; ++ list = rht_dereference(list->next, ht); ++ p = rht_obj(ht, pos); ++ ++ sprintf(buff, "%s val %d (tid=%d)%s", buff, p->value.id, p->value.tid, ++ list? ", " : " "); ++ cnt++; ++ } while (list); ++ ++ pos = next, ++ next = !rht_is_a_nulls(pos) ? ++ rht_dereference(pos->next, ht) : NULL; ++ ++ sprintf(buff, "%s]]%s", buff, !rht_is_a_nulls(pos) ? " -> " : ""); ++ } ++ } ++ printk(KERN_ERR "\n---- ht: ----%s\n-------------\n", buff); ++ ++ return cnt; ++} ++ ++static int __init test_insert_dup(struct test_obj_rhl *rhl_test_objects, ++ int cnt, bool slow) ++{ ++ struct rhltable rhlt; ++ unsigned int i, ret; ++ const char *key; ++ int err = 0; ++ ++ err = rhltable_init(&rhlt, &test_rht_params_dup); ++ if (WARN_ON(err)) ++ return err; ++ ++ for (i = 0; i < cnt; i++) { ++ rhl_test_objects[i].value.tid = i; ++ key = rht_obj(&rhlt.ht, &rhl_test_objects[i].list_node.rhead); ++ key += test_rht_params_dup.key_offset; ++ ++ if (slow) { ++ err = PTR_ERR(rhashtable_insert_slow(&rhlt.ht, key, ++ &rhl_test_objects[i].list_node.rhead)); ++ if (err == -EAGAIN) ++ err = 0; ++ } else ++ err = rhltable_insert(&rhlt, ++ &rhl_test_objects[i].list_node, ++ test_rht_params_dup); ++ if (WARN(err, "error %d on element %d/%d (%s)\n", err, i, cnt, slow? "slow" : "fast")) ++ goto skip_print; ++ } ++ ++ ret = print_ht(&rhlt); ++ WARN(ret != cnt, "missing rhltable elements (%d != %d, %s)\n", ret, cnt, slow? "slow" : "fast"); ++ ++skip_print: ++ rhltable_destroy(&rhlt); ++ ++ return 0; ++} ++ ++static int __init test_insert_duplicates_run(void) ++{ ++ struct test_obj_rhl rhl_test_objects[3] = {}; ++ ++ pr_info("test inserting duplicates\n"); ++ ++ /* two different values that map to same bucket */ ++ rhl_test_objects[0].value.id = 1; ++ rhl_test_objects[1].value.id = 21; ++ ++ /* and another duplicate with same as [0] value ++ * which will be second on the bucket list */ ++ rhl_test_objects[2].value.id = rhl_test_objects[0].value.id; ++ ++ test_insert_dup(rhl_test_objects, 2, false); ++ test_insert_dup(rhl_test_objects, 3, false); ++ test_insert_dup(rhl_test_objects, 2, true); ++ test_insert_dup(rhl_test_objects, 3, true); ++ ++ return 0; ++} ++ + static int thread_lookup_test(struct thread_data *tdata) + { + unsigned int entries = tdata->entries; +@@ -617,6 +749,8 @@ static int __init test_rht_init(void) + do_div(total_time, runs); + pr_info("Average test time: %llu\n", total_time); + ++ test_insert_duplicates_run(); ++ + if (!tcount) + return 0; + +diff --git a/net/core/dev.c b/net/core/dev.c +index a2a89acd0de8..f3fbd10a0632 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -3247,15 +3247,23 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, + #if IS_ENABLED(CONFIG_CGROUP_NET_PRIO) + static void skb_update_prio(struct sk_buff *skb) + { +- struct netprio_map *map = rcu_dereference_bh(skb->dev->priomap); ++ const struct netprio_map *map; ++ const struct sock *sk; ++ unsigned int prioidx; + +- if (!skb->priority && skb->sk && map) { +- unsigned int prioidx = +- sock_cgroup_prioidx(&skb->sk->sk_cgrp_data); ++ if (skb->priority) ++ return; ++ map = rcu_dereference_bh(skb->dev->priomap); ++ if (!map) ++ return; ++ sk = skb_to_full_sk(skb); ++ if (!sk) ++ return; + +- if (prioidx < map->priomap_len) +- skb->priority = map->priomap[prioidx]; +- } ++ prioidx = sock_cgroup_prioidx(&sk->sk_cgrp_data); ++ ++ if (prioidx < map->priomap_len) ++ skb->priority = map->priomap[prioidx]; + } + #else + #define skb_update_prio(skb) +diff --git a/net/core/devlink.c b/net/core/devlink.c +index 7d430c1d9c3e..5ba973311025 100644 +--- a/net/core/devlink.c ++++ b/net/core/devlink.c +@@ -1776,7 +1776,7 @@ static int devlink_dpipe_tables_fill(struct genl_info *info, + if (!nlh) { + err = devlink_dpipe_send_and_alloc_skb(&skb, info); + if (err) +- goto err_skb_send_alloc; ++ return err; + goto send_done; + } + +@@ -1785,7 +1785,6 @@ static int devlink_dpipe_tables_fill(struct genl_info *info, + nla_put_failure: + err = -EMSGSIZE; + err_table_put: +-err_skb_send_alloc: + genlmsg_cancel(skb, hdr); + nlmsg_free(skb); + return err; +@@ -2051,7 +2050,7 @@ static int devlink_dpipe_entries_fill(struct genl_info *info, + table->counters_enabled, + &dump_ctx); + if (err) +- goto err_entries_dump; ++ return err; + + send_done: + nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq, +@@ -2059,16 +2058,10 @@ static int devlink_dpipe_entries_fill(struct genl_info *info, + if (!nlh) { + err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info); + if (err) +- goto err_skb_send_alloc; ++ return err; + goto send_done; + } + return genlmsg_reply(dump_ctx.skb, info); +- +-err_entries_dump: +-err_skb_send_alloc: +- genlmsg_cancel(dump_ctx.skb, dump_ctx.hdr); +- nlmsg_free(dump_ctx.skb); +- return err; + } + + static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb, +@@ -2207,7 +2200,7 @@ static int devlink_dpipe_headers_fill(struct genl_info *info, + if (!nlh) { + err = devlink_dpipe_send_and_alloc_skb(&skb, info); + if (err) +- goto err_skb_send_alloc; ++ return err; + goto send_done; + } + return genlmsg_reply(skb, info); +@@ -2215,7 +2208,6 @@ static int devlink_dpipe_headers_fill(struct genl_info *info, + nla_put_failure: + err = -EMSGSIZE; + err_table_put: +-err_skb_send_alloc: + genlmsg_cancel(skb, hdr); + nlmsg_free(skb); + return err; +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 08f574081315..3538ba8771e9 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -4173,7 +4173,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) + + skb_queue_tail(&sk->sk_error_queue, skb); + if (!sock_flag(sk, SOCK_DEAD)) +- sk->sk_data_ready(sk); ++ sk->sk_error_report(sk); + return 0; + } + EXPORT_SYMBOL(sock_queue_err_skb); +diff --git a/net/dccp/proto.c b/net/dccp/proto.c +index 9d43c1f40274..ff3b058cf58c 100644 +--- a/net/dccp/proto.c ++++ b/net/dccp/proto.c +@@ -789,6 +789,11 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + if (skb == NULL) + goto out_release; + ++ if (sk->sk_state == DCCP_CLOSED) { ++ rc = -ENOTCONN; ++ goto out_discard; ++ } ++ + skb_reserve(skb, sk->sk_prot->max_header); + rc = memcpy_from_msg(skb_put(skb, len), msg, len); + if (rc != 0) +diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c +index 84611d7fcfa2..3c9cee268b8a 100644 +--- a/net/dsa/legacy.c ++++ b/net/dsa/legacy.c +@@ -194,7 +194,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, + ds->ports[i].dn = cd->port_dn[i]; + ds->ports[i].cpu_dp = dst->cpu_dp; + +- if (dsa_is_user_port(ds, i)) ++ if (!dsa_is_user_port(ds, i)) + continue; + + ret = dsa_slave_create(&ds->ports[i]); +diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c +index 974765b7d92a..e9f0489e4229 100644 +--- a/net/ieee802154/6lowpan/core.c ++++ b/net/ieee802154/6lowpan/core.c +@@ -206,9 +206,13 @@ static inline void lowpan_netlink_fini(void) + static int lowpan_device_event(struct notifier_block *unused, + unsigned long event, void *ptr) + { +- struct net_device *wdev = netdev_notifier_info_to_dev(ptr); ++ struct net_device *ndev = netdev_notifier_info_to_dev(ptr); ++ struct wpan_dev *wpan_dev; + +- if (wdev->type != ARPHRD_IEEE802154) ++ if (ndev->type != ARPHRD_IEEE802154) ++ return NOTIFY_DONE; ++ wpan_dev = ndev->ieee802154_ptr; ++ if (!wpan_dev) + return NOTIFY_DONE; + + switch (event) { +@@ -217,8 +221,8 @@ static int lowpan_device_event(struct notifier_block *unused, + * also delete possible lowpan interfaces which belongs + * to the wpan interface. + */ +- if (wdev->ieee802154_ptr->lowpan_dev) +- lowpan_dellink(wdev->ieee802154_ptr->lowpan_dev, NULL); ++ if (wpan_dev->lowpan_dev) ++ lowpan_dellink(wpan_dev->lowpan_dev, NULL); + break; + default: + return NOTIFY_DONE; +diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c +index 26a3d0315728..e8ec28999f5c 100644 +--- a/net/ipv4/inet_fragment.c ++++ b/net/ipv4/inet_fragment.c +@@ -119,6 +119,9 @@ static void inet_frag_secret_rebuild(struct inet_frags *f) + + static bool inet_fragq_should_evict(const struct inet_frag_queue *q) + { ++ if (!hlist_unhashed(&q->list_evictor)) ++ return false; ++ + return q->net->low_thresh == 0 || + frag_mem_limit(q->net) >= q->net->low_thresh; + } +diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index f56aab54e0c8..1e70ed5244ea 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -258,7 +258,8 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc, + src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); + if (!ipv6_addr_v4mapped(&src_info->ipi6_addr)) + return -EINVAL; +- ipc->oif = src_info->ipi6_ifindex; ++ if (src_info->ipi6_ifindex) ++ ipc->oif = src_info->ipi6_ifindex; + ipc->addr = src_info->ipi6_addr.s6_addr32[3]; + continue; + } +@@ -288,7 +289,8 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc, + if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct in_pktinfo))) + return -EINVAL; + info = (struct in_pktinfo *)CMSG_DATA(cmsg); +- ipc->oif = info->ipi_ifindex; ++ if (info->ipi_ifindex) ++ ipc->oif = info->ipi_ifindex; + ipc->addr = info->ipi_spec_dst.s_addr; + break; + } +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index c821f5d68720..2eb91b97a062 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -3542,6 +3542,7 @@ int tcp_abort(struct sock *sk, int err) + + bh_unlock_sock(sk); + local_bh_enable(); ++ tcp_write_queue_purge(sk); + release_sock(sk); + return 0; + } +diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c +index 388158c9d9f6..c721140a7d79 100644 +--- a/net/ipv4/tcp_timer.c ++++ b/net/ipv4/tcp_timer.c +@@ -34,6 +34,7 @@ static void tcp_write_err(struct sock *sk) + sk->sk_err = sk->sk_err_soft ? : ETIMEDOUT; + sk->sk_error_report(sk); + ++ tcp_write_queue_purge(sk); + tcp_done(sk); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONTIMEOUT); + } +diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c +index a1f918713006..287112da3c06 100644 +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -146,10 +146,12 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, + struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; + struct inet_sock *inet = inet_sk(sk); + struct ipv6_pinfo *np = inet6_sk(sk); +- struct in6_addr *daddr; ++ struct in6_addr *daddr, old_daddr; ++ __be32 fl6_flowlabel = 0; ++ __be32 old_fl6_flowlabel; ++ __be16 old_dport; + int addr_type; + int err; +- __be32 fl6_flowlabel = 0; + + if (usin->sin6_family == AF_INET) { + if (__ipv6_only_sock(sk)) +@@ -239,9 +241,13 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, + } + } + ++ /* save the current peer information before updating it */ ++ old_daddr = sk->sk_v6_daddr; ++ old_fl6_flowlabel = np->flow_label; ++ old_dport = inet->inet_dport; ++ + sk->sk_v6_daddr = *daddr; + np->flow_label = fl6_flowlabel; +- + inet->inet_dport = usin->sin6_port; + + /* +@@ -251,11 +257,12 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, + + err = ip6_datagram_dst_update(sk, true); + if (err) { +- /* Reset daddr and dport so that udp_v6_early_demux() +- * fails to find this socket ++ /* Restore the socket peer info, to keep it consistent with ++ * the old socket state + */ +- memset(&sk->sk_v6_daddr, 0, sizeof(sk->sk_v6_daddr)); +- inet->inet_dport = 0; ++ sk->sk_v6_daddr = old_daddr; ++ np->flow_label = old_fl6_flowlabel; ++ inet->inet_dport = old_dport; + goto out; + } + +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c +index f61a5b613b52..ba5e04c6ae17 100644 +--- a/net/ipv6/ndisc.c ++++ b/net/ipv6/ndisc.c +@@ -1554,7 +1554,8 @@ static void ndisc_fill_redirect_hdr_option(struct sk_buff *skb, + *(opt++) = (rd_len >> 3); + opt += 6; + +- memcpy(opt, ipv6_hdr(orig_skb), rd_len - 8); ++ skb_copy_bits(orig_skb, skb_network_offset(orig_skb), opt, ++ rd_len - 8); + } + + void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index a560fb1d0230..08a2a65d3304 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -1510,7 +1510,30 @@ static void rt6_exceptions_remove_prefsrc(struct rt6_info *rt) + } + } + +-static void rt6_exceptions_update_pmtu(struct rt6_info *rt, int mtu) ++static bool rt6_mtu_change_route_allowed(struct inet6_dev *idev, ++ struct rt6_info *rt, int mtu) ++{ ++ /* If the new MTU is lower than the route PMTU, this new MTU will be the ++ * lowest MTU in the path: always allow updating the route PMTU to ++ * reflect PMTU decreases. ++ * ++ * If the new MTU is higher, and the route PMTU is equal to the local ++ * MTU, this means the old MTU is the lowest in the path, so allow ++ * updating it: if other nodes now have lower MTUs, PMTU discovery will ++ * handle this. ++ */ ++ ++ if (dst_mtu(&rt->dst) >= mtu) ++ return true; ++ ++ if (dst_mtu(&rt->dst) == idev->cnf.mtu6) ++ return true; ++ ++ return false; ++} ++ ++static void rt6_exceptions_update_pmtu(struct inet6_dev *idev, ++ struct rt6_info *rt, int mtu) + { + struct rt6_exception_bucket *bucket; + struct rt6_exception *rt6_ex; +@@ -1519,20 +1542,22 @@ static void rt6_exceptions_update_pmtu(struct rt6_info *rt, int mtu) + bucket = rcu_dereference_protected(rt->rt6i_exception_bucket, + lockdep_is_held(&rt6_exception_lock)); + +- if (bucket) { +- for (i = 0; i < FIB6_EXCEPTION_BUCKET_SIZE; i++) { +- hlist_for_each_entry(rt6_ex, &bucket->chain, hlist) { +- struct rt6_info *entry = rt6_ex->rt6i; +- /* For RTF_CACHE with rt6i_pmtu == 0 +- * (i.e. a redirected route), +- * the metrics of its rt->dst.from has already +- * been updated. +- */ +- if (entry->rt6i_pmtu && entry->rt6i_pmtu > mtu) +- entry->rt6i_pmtu = mtu; +- } +- bucket++; ++ if (!bucket) ++ return; ++ ++ for (i = 0; i < FIB6_EXCEPTION_BUCKET_SIZE; i++) { ++ hlist_for_each_entry(rt6_ex, &bucket->chain, hlist) { ++ struct rt6_info *entry = rt6_ex->rt6i; ++ ++ /* For RTF_CACHE with rt6i_pmtu == 0 (i.e. a redirected ++ * route), the metrics of its rt->dst.from have already ++ * been updated. ++ */ ++ if (entry->rt6i_pmtu && ++ rt6_mtu_change_route_allowed(idev, entry, mtu)) ++ entry->rt6i_pmtu = mtu; + } ++ bucket++; + } + } + +@@ -3521,25 +3546,13 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) + Since RFC 1981 doesn't include administrative MTU increase + update PMTU increase is a MUST. (i.e. jumbo frame) + */ +- /* +- If new MTU is less than route PMTU, this new MTU will be the +- lowest MTU in the path, update the route PMTU to reflect PMTU +- decreases; if new MTU is greater than route PMTU, and the +- old MTU is the lowest MTU in the path, update the route PMTU +- to reflect the increase. In this case if the other nodes' MTU +- also have the lowest MTU, TOO BIG MESSAGE will be lead to +- PMTU discovery. +- */ + if (rt->dst.dev == arg->dev && +- dst_metric_raw(&rt->dst, RTAX_MTU) && + !dst_metric_locked(&rt->dst, RTAX_MTU)) { + spin_lock_bh(&rt6_exception_lock); +- if (dst_mtu(&rt->dst) >= arg->mtu || +- (dst_mtu(&rt->dst) < arg->mtu && +- dst_mtu(&rt->dst) == idev->cnf.mtu6)) { ++ if (dst_metric_raw(&rt->dst, RTAX_MTU) && ++ rt6_mtu_change_route_allowed(idev, rt, arg->mtu)) + dst_metric_set(&rt->dst, RTAX_MTU, arg->mtu); +- } +- rt6_exceptions_update_pmtu(rt, arg->mtu); ++ rt6_exceptions_update_pmtu(idev, rt, arg->mtu); + spin_unlock_bh(&rt6_exception_lock); + } + return 0; +diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c +index bd6cc688bd19..7a78dcfda68a 100644 +--- a/net/ipv6/seg6_iptunnel.c ++++ b/net/ipv6/seg6_iptunnel.c +@@ -93,7 +93,8 @@ static void set_tun_src(struct net *net, struct net_device *dev, + /* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */ + int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) + { +- struct net *net = dev_net(skb_dst(skb)->dev); ++ struct dst_entry *dst = skb_dst(skb); ++ struct net *net = dev_net(dst->dev); + struct ipv6hdr *hdr, *inner_hdr; + struct ipv6_sr_hdr *isrh; + int hdrlen, tot_len, err; +@@ -134,7 +135,7 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) + isrh->nexthdr = proto; + + hdr->daddr = isrh->segments[isrh->first_segment]; +- set_tun_src(net, skb->dev, &hdr->daddr, &hdr->saddr); ++ set_tun_src(net, ip6_dst_idev(dst)->dev, &hdr->daddr, &hdr->saddr); + + #ifdef CONFIG_IPV6_SEG6_HMAC + if (sr_has_hmac(isrh)) { +@@ -418,7 +419,7 @@ static int seg6_build_state(struct nlattr *nla, + + slwt = seg6_lwt_lwtunnel(newts); + +- err = dst_cache_init(&slwt->cache, GFP_KERNEL); ++ err = dst_cache_init(&slwt->cache, GFP_ATOMIC); + if (err) { + kfree(newts); + return err; +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index 148533169b1d..ca98276c2709 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -2433,9 +2433,11 @@ static int afiucv_iucv_init(void) + af_iucv_dev->driver = &af_iucv_driver; + err = device_register(af_iucv_dev); + if (err) +- goto out_driver; ++ goto out_iucv_dev; + return 0; + ++out_iucv_dev: ++ put_device(af_iucv_dev); + out_driver: + driver_unregister(&af_iucv_driver); + out_iucv: +diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c +index 4a8d407f8902..3f15ffd356da 100644 +--- a/net/kcm/kcmsock.c ++++ b/net/kcm/kcmsock.c +@@ -1381,24 +1381,32 @@ static int kcm_attach(struct socket *sock, struct socket *csock, + .parse_msg = kcm_parse_func_strparser, + .read_sock_done = kcm_read_sock_done, + }; +- int err; ++ int err = 0; + + csk = csock->sk; + if (!csk) + return -EINVAL; + ++ lock_sock(csk); ++ + /* Only allow TCP sockets to be attached for now */ + if ((csk->sk_family != AF_INET && csk->sk_family != AF_INET6) || +- csk->sk_protocol != IPPROTO_TCP) +- return -EOPNOTSUPP; ++ csk->sk_protocol != IPPROTO_TCP) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } + + /* Don't allow listeners or closed sockets */ +- if (csk->sk_state == TCP_LISTEN || csk->sk_state == TCP_CLOSE) +- return -EOPNOTSUPP; ++ if (csk->sk_state == TCP_LISTEN || csk->sk_state == TCP_CLOSE) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } + + psock = kmem_cache_zalloc(kcm_psockp, GFP_KERNEL); +- if (!psock) +- return -ENOMEM; ++ if (!psock) { ++ err = -ENOMEM; ++ goto out; ++ } + + psock->mux = mux; + psock->sk = csk; +@@ -1407,7 +1415,7 @@ static int kcm_attach(struct socket *sock, struct socket *csock, + err = strp_init(&psock->strp, csk, &cb); + if (err) { + kmem_cache_free(kcm_psockp, psock); +- return err; ++ goto out; + } + + write_lock_bh(&csk->sk_callback_lock); +@@ -1419,7 +1427,8 @@ static int kcm_attach(struct socket *sock, struct socket *csock, + write_unlock_bh(&csk->sk_callback_lock); + strp_done(&psock->strp); + kmem_cache_free(kcm_psockp, psock); +- return -EALREADY; ++ err = -EALREADY; ++ goto out; + } + + psock->save_data_ready = csk->sk_data_ready; +@@ -1455,7 +1464,10 @@ static int kcm_attach(struct socket *sock, struct socket *csock, + /* Schedule RX work in case there are already bytes queued */ + strp_check_rcv(&psock->strp); + +- return 0; ++out: ++ release_sock(csk); ++ ++ return err; + } + + static int kcm_attach_ioctl(struct socket *sock, struct kcm_attach *info) +@@ -1507,6 +1519,7 @@ static void kcm_unattach(struct kcm_psock *psock) + + if (WARN_ON(psock->rx_kcm)) { + write_unlock_bh(&csk->sk_callback_lock); ++ release_sock(csk); + return; + } + +diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c +index 861b67c34191..e8b26afeb194 100644 +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -1466,9 +1466,14 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 + encap = cfg->encap; + + /* Quick sanity checks */ ++ err = -EPROTONOSUPPORT; ++ if (sk->sk_type != SOCK_DGRAM) { ++ pr_debug("tunl %hu: fd %d wrong socket type\n", ++ tunnel_id, fd); ++ goto err; ++ } + switch (encap) { + case L2TP_ENCAPTYPE_UDP: +- err = -EPROTONOSUPPORT; + if (sk->sk_protocol != IPPROTO_UDP) { + pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n", + tunnel_id, fd, sk->sk_protocol, IPPROTO_UDP); +@@ -1476,7 +1481,6 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 + } + break; + case L2TP_ENCAPTYPE_IP: +- err = -EPROTONOSUPPORT; + if (sk->sk_protocol != IPPROTO_L2TP) { + pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n", + tunnel_id, fd, sk->sk_protocol, IPPROTO_L2TP); +diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c +index 6f02499ef007..b9ce82c9440f 100644 +--- a/net/netlink/genetlink.c ++++ b/net/netlink/genetlink.c +@@ -1106,7 +1106,7 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group, + if (!err) + delivered = true; + else if (err != -ESRCH) +- goto error; ++ return err; + return delivered ? 0 : -ESRCH; + error: + kfree_skb(skb); +diff --git a/net/openvswitch/meter.c b/net/openvswitch/meter.c +index 3fbfc78991ac..0d961f09d0c7 100644 +--- a/net/openvswitch/meter.c ++++ b/net/openvswitch/meter.c +@@ -242,14 +242,20 @@ static struct dp_meter *dp_meter_create(struct nlattr **a) + + band->type = nla_get_u32(attr[OVS_BAND_ATTR_TYPE]); + band->rate = nla_get_u32(attr[OVS_BAND_ATTR_RATE]); ++ if (band->rate == 0) { ++ err = -EINVAL; ++ goto exit_free_meter; ++ } ++ + band->burst_size = nla_get_u32(attr[OVS_BAND_ATTR_BURST]); + /* Figure out max delta_t that is enough to fill any bucket. + * Keep max_delta_t size to the bucket units: + * pkts => 1/1000 packets, kilobits => bits. ++ * ++ * Start with a full bucket. + */ +- band_max_delta_t = (band->burst_size + band->rate) * 1000; +- /* Start with a full bucket. */ +- band->bucket = band_max_delta_t; ++ band->bucket = (band->burst_size + band->rate) * 1000; ++ band_max_delta_t = band->bucket / band->rate; + if (band_max_delta_t > meter->max_delta_t) + meter->max_delta_t = band_max_delta_t; + band++; +diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c +index 30c96274c638..22bf1a376b91 100644 +--- a/net/sched/act_tunnel_key.c ++++ b/net/sched/act_tunnel_key.c +@@ -153,6 +153,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, + metadata->u.tun_info.mode |= IP_TUNNEL_INFO_TX; + break; + default: ++ ret = -EINVAL; + goto err_out; + } + +diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c +index dd70924cbcdf..2aeca57f9bd0 100644 +--- a/net/sched/sch_netem.c ++++ b/net/sched/sch_netem.c +@@ -509,7 +509,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, + } + + if (unlikely(sch->q.qlen >= sch->limit)) +- return qdisc_drop(skb, sch, to_free); ++ return qdisc_drop_all(skb, sch, to_free); + + qdisc_qstats_backlog_inc(sch, skb); +
