mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-27 17:21:34 +00:00
1401 lines
43 KiB
Diff
1401 lines
43 KiB
Diff
diff --git a/Makefile b/Makefile
|
|
index 99e31da48422..c4c681b53ff0 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 4
|
|
PATCHLEVEL = 14
|
|
-SUBLEVEL = 31
|
|
+SUBLEVEL = 32
|
|
EXTRAVERSION =
|
|
NAME = Petit Gorille
|
|
|
|
diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c
|
|
index c6163874e4e7..c770ca37c9b2 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 eb441e5e2cd8..1e856e8b9a92 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 82e401df199e..a2006f5fc26f 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 42258060f142..4f6e9d3470d5 100644
|
|
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
|
|
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
|
|
@@ -2022,7 +2022,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;
|
|
}
|
|
@@ -2292,7 +2291,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));
|
|
|
|
@@ -2325,8 +2323,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 311539c6625f..eb2ea231c7ca 100644
|
|
--- a/drivers/net/ethernet/freescale/fec_main.c
|
|
+++ b/drivers/net/ethernet/freescale/fec_main.c
|
|
@@ -3565,6 +3565,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 9d989c96278c..e41f28602535 100644
|
|
--- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c
|
|
+++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c
|
|
@@ -1663,6 +1663,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;
|
|
@@ -1671,6 +1678,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]);
|
|
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
|
|
index e5ee9f274a71..6eab2c632c75 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 14b646b3b084..a5bb7b19040e 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 176fc0906bfe..0f35597553f4 100644
|
|
--- a/drivers/net/macvlan.c
|
|
+++ b/drivers/net/macvlan.c
|
|
@@ -1037,7 +1037,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 38cd2e8fae23..34b24d7e1e2f 100644
|
|
--- a/drivers/net/ppp/ppp_generic.c
|
|
+++ b/drivers/net/ppp/ppp_generic.c
|
|
@@ -256,7 +256,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);
|
|
@@ -512,13 +512,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;
|
|
}
|
|
@@ -1264,8 +1263,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:
|
|
@@ -1417,13 +1416,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);
|
|
@@ -1437,7 +1437,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();
|
|
|
|
@@ -1445,7 +1445,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();
|
|
@@ -1455,6 +1455,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");
|
|
}
|
|
@@ -1939,7 +1941,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 ae53e899259f..23cd41c82210 100644
|
|
--- a/drivers/net/team/team.c
|
|
+++ b/drivers/net/team/team.c
|
|
@@ -2394,7 +2394,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;
|
|
}
|
|
|
|
@@ -2680,7 +2680,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 145b57762d8f..939b5b5e97ef 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;
|
|
@@ -5061,8 +5072,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 5a973ebcb13c..521293b1f4fa 100644
|
|
--- a/drivers/s390/net/qeth_l2_main.c
|
|
+++ b/drivers/s390/net/qeth_l2_main.c
|
|
@@ -935,8 +935,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 96576e729222..1c62cbbaa66f 100644
|
|
--- a/drivers/s390/net/qeth_l3_main.c
|
|
+++ b/drivers/s390/net/qeth_l3_main.c
|
|
@@ -3046,8 +3046,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 18eefc3f1abe..0c6065dba48a 100644
|
|
--- a/drivers/soc/fsl/qbman/qman.c
|
|
+++ b/drivers/soc/fsl/qbman/qman.c
|
|
@@ -2414,39 +2414,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 1dff0a478b45..4e8f77504a57 100644
|
|
--- a/include/linux/cgroup-defs.h
|
|
+++ b/include/linux/cgroup-defs.h
|
|
@@ -696,13 +696,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 600076e1ce84..dca9e926b88f 100644
|
|
--- a/include/linux/phy.h
|
|
+++ b/include/linux/phy.h
|
|
@@ -895,7 +895,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 6073e8bae025..f59acacaa265 100644
|
|
--- a/include/net/sch_generic.h
|
|
+++ b/include/net/sch_generic.h
|
|
@@ -723,6 +723,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)
|
|
@@ -843,6 +853,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/include/net/tcp.h b/include/net/tcp.h
|
|
index 0a13574134b8..d323d4fa742c 100644
|
|
--- a/include/net/tcp.h
|
|
+++ b/include/net/tcp.h
|
|
@@ -1600,6 +1600,11 @@ enum tcp_chrono {
|
|
void tcp_chrono_start(struct sock *sk, const enum tcp_chrono type);
|
|
void tcp_chrono_stop(struct sock *sk, const enum tcp_chrono type);
|
|
|
|
+static inline void tcp_init_send_head(struct sock *sk)
|
|
+{
|
|
+ sk->sk_send_head = NULL;
|
|
+}
|
|
+
|
|
/* write queue abstraction */
|
|
static inline void tcp_write_queue_purge(struct sock *sk)
|
|
{
|
|
@@ -1610,6 +1615,7 @@ static inline void tcp_write_queue_purge(struct sock *sk)
|
|
sk_wmem_free_skb(sk, skb);
|
|
sk_mem_reclaim(sk);
|
|
tcp_clear_all_retrans_hints(tcp_sk(sk));
|
|
+ tcp_init_send_head(sk);
|
|
}
|
|
|
|
static inline struct sk_buff *tcp_write_queue_head(const struct sock *sk)
|
|
@@ -1672,11 +1678,6 @@ static inline void tcp_check_send_head(struct sock *sk, struct sk_buff *skb_unli
|
|
tcp_sk(sk)->highest_sack = NULL;
|
|
}
|
|
|
|
-static inline void tcp_init_send_head(struct sock *sk)
|
|
-{
|
|
- sk->sk_send_head = NULL;
|
|
-}
|
|
-
|
|
static inline void __tcp_add_write_queue_tail(struct sock *sk, struct sk_buff *skb)
|
|
{
|
|
__skb_queue_tail(&sk->sk_write_queue, skb);
|
|
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/net/core/dev.c b/net/core/dev.c
|
|
index c75ef9d8105a..387af3415385 100644
|
|
--- a/net/core/dev.c
|
|
+++ b/net/core/dev.c
|
|
@@ -3224,15 +3224,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 cc811add68c6..564beb7e6d1c 100644
|
|
--- a/net/core/skbuff.c
|
|
+++ b/net/core/skbuff.c
|
|
@@ -4171,7 +4171,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/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 af74d0433453..e691705f0a85 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 fe11128d7df4..38b9a6276a9d 100644
|
|
--- a/net/ipv4/tcp.c
|
|
+++ b/net/ipv4/tcp.c
|
|
@@ -3445,6 +3445,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 14ac7df95380..a845b7692c1b 100644
|
|
--- a/net/ipv4/tcp_timer.c
|
|
+++ b/net/ipv4/tcp_timer.c
|
|
@@ -36,6 +36,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 2a937c8d19e9..dd28005efb97 100644
|
|
--- a/net/ipv6/ndisc.c
|
|
+++ b/net/ipv6/ndisc.c
|
|
@@ -1546,7 +1546,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/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 58d53b907d53..9db49805b7be 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 af22aa8ae35b..490d7360222e 100644
|
|
--- a/net/l2tp/l2tp_core.c
|
|
+++ b/net/l2tp/l2tp_core.c
|
|
@@ -1562,9 +1562,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);
|
|
@@ -1572,7 +1577,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/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 b1266e75ca43..8c8df75dbead 100644
|
|
--- a/net/sched/sch_netem.c
|
|
+++ b/net/sched/sch_netem.c
|
|
@@ -513,7 +513,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);
|
|
|