Merge tag 'net-6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Pull networking fixes from Paolo Abeni:
 "No fixes from any subtree.

  Current release - regressions:

   - net: fix the missing unlock for detached devices

  Previous releases - regressions:

   - sched: fix UAF vulnerability in HFSC qdisc

   - lwtunnel: disable BHs when required

   - mptcp: pm: defer freeing of MPTCP userspace path manager entries

   - tipc: fix NULL pointer dereference in tipc_mon_reinit_self()

   - eth: virtio-net: disable delayed refill when pausing rx

  Previous releases - always broken:

   - phylink: fix suspend/resume with WoL enabled and link down

   - eth:
       - mlx5: fix null-ptr-deref in mlx5_create_{inner_,}ttc_table()
       - xen-netfront: handle NULL returned by xdp_convert_buff_to_frame()
       - enetc: fix frame corruption on bpf_xdp_adjust_head/tail() and XDP_PASS
       - stmmac: fix dwmac1000 ptp timestamp status offset
       - pds_core: prevent possible adminq overflow/stuck condition

  Misc:

   - a bunch of MAINTAINERS updates"

* tag 'net-6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (32 commits)
  net: stmmac: fix multiplication overflow when reading timestamp
  net: stmmac: fix dwmac1000 ptp timestamp status offset
  net: dp83822: Fix OF_MDIO config check
  pds_core: make wait_context part of q_info
  pds_core: Remove unnecessary check in pds_client_adminq_cmd()
  pds_core: handle unsupported PDS_CORE_CMD_FW_CONTROL result
  pds_core: Prevent possible adminq overflow/stuck condition
  net: dsa: mt7530: sync driver-specific behavior of MT7531 variants
  selftests/tc-testing: Add test for HFSC queue emptying during peek operation
  net_sched: hfsc: Fix a potential UAF in hfsc_dequeue() too
  net_sched: hfsc: Fix a UAF vulnerability in class handling
  selftests: mptcp: diag: use mptcp_lib_get_info_value
  mptcp: pm: Defer freeing of MPTCP userspace path manager entries
  net: ethernet: mtk_eth_soc: net: revise NETSYSv3 hardware configuration
  tipc: fix NULL pointer dereference in tipc_mon_reinit_self()
  virtio-net: disable delayed refill when pausing rx
  net: phy: leds: fix memory leak
  net: phylink: mac_link_(up|down)() clarifications
  net: phylink: fix suspend/resume with WoL enabled and link down
  net: lwtunnel: disable BHs when required
  ...
This commit is contained in:
Linus Torvalds
2025-04-24 09:14:50 -07:00
29 changed files with 345 additions and 196 deletions
+9
View File
@@ -3191,6 +3191,12 @@ M: Dinh Nguyen <dinguyen@kernel.org>
S: Maintained
F: drivers/clk/socfpga/
ARM/SOCFPGA DWMAC GLUE LAYER
M: Maxime Chevallier <maxime.chevallier@bootlin.com>
S: Maintained
F: Documentation/devicetree/bindings/net/socfpga-dwmac.txt
F: drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
ARM/SOCFPGA EDAC BINDINGS
M: Matthew Gerlach <matthew.gerlach@altera.com>
S: Maintained
@@ -16812,6 +16818,7 @@ F: Documentation/networking/net_cachelines/net_device.rst
F: drivers/connector/
F: drivers/net/
F: drivers/ptp/
F: drivers/s390/net/
F: include/dt-bindings/net/
F: include/linux/cn_proc.h
F: include/linux/etherdevice.h
@@ -16821,6 +16828,7 @@ F: include/linux/fddidevice.h
F: include/linux/hippidevice.h
F: include/linux/if_*
F: include/linux/inetdevice.h
F: include/linux/ism.h
F: include/linux/netdev*
F: include/linux/platform_data/wiznet.h
F: include/uapi/linux/cn_proc.h
@@ -21312,6 +21320,7 @@ L: linux-s390@vger.kernel.org
L: netdev@vger.kernel.org
S: Supported
F: drivers/s390/net/
F: include/linux/ism.h
S390 PCI SUBSYSTEM
M: Niklas Schnelle <schnelle@linux.ibm.com>
+3 -3
View File
@@ -2419,6 +2419,9 @@ mt7531_setup_common(struct dsa_switch *ds)
struct mt7530_priv *priv = ds->priv;
int ret, i;
ds->assisted_learning_on_cpu_port = true;
ds->mtu_enforcement_ingress = true;
mt753x_trap_frames(priv);
/* Enable and reset MIB counters */
@@ -2571,9 +2574,6 @@ mt7531_setup(struct dsa_switch *ds)
if (ret)
return ret;
ds->assisted_learning_on_cpu_port = true;
ds->mtu_enforcement_ingress = true;
return 0;
}
+14 -22
View File
@@ -5,11 +5,6 @@
#include "core.h"
struct pdsc_wait_context {
struct pdsc_qcq *qcq;
struct completion wait_completion;
};
static int pdsc_process_notifyq(struct pdsc_qcq *qcq)
{
union pds_core_notifyq_comp *comp;
@@ -109,10 +104,10 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq)
q_info = &q->info[q->tail_idx];
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
/* Copy out the completion data */
memcpy(q_info->dest, comp, sizeof(*comp));
complete_all(&q_info->wc->wait_completion);
if (!completion_done(&q_info->completion)) {
memcpy(q_info->dest, comp, sizeof(*comp));
complete(&q_info->completion);
}
if (cq->tail_idx == cq->num_descs - 1)
cq->done_color = !cq->done_color;
@@ -162,8 +157,7 @@ irqreturn_t pdsc_adminq_isr(int irq, void *data)
static int __pdsc_adminq_post(struct pdsc *pdsc,
struct pdsc_qcq *qcq,
union pds_core_adminq_cmd *cmd,
union pds_core_adminq_comp *comp,
struct pdsc_wait_context *wc)
union pds_core_adminq_comp *comp)
{
struct pdsc_queue *q = &qcq->q;
struct pdsc_q_info *q_info;
@@ -205,9 +199,9 @@ static int __pdsc_adminq_post(struct pdsc *pdsc,
/* Post the request */
index = q->head_idx;
q_info = &q->info[index];
q_info->wc = wc;
q_info->dest = comp;
memcpy(q_info->desc, cmd, sizeof(*cmd));
reinit_completion(&q_info->completion);
dev_dbg(pdsc->dev, "head_idx %d tail_idx %d\n",
q->head_idx, q->tail_idx);
@@ -231,16 +225,13 @@ int pdsc_adminq_post(struct pdsc *pdsc,
union pds_core_adminq_comp *comp,
bool fast_poll)
{
struct pdsc_wait_context wc = {
.wait_completion =
COMPLETION_INITIALIZER_ONSTACK(wc.wait_completion),
};
unsigned long poll_interval = 1;
unsigned long poll_jiffies;
unsigned long time_limit;
unsigned long time_start;
unsigned long time_done;
unsigned long remaining;
struct completion *wc;
int err = 0;
int index;
@@ -250,20 +241,19 @@ int pdsc_adminq_post(struct pdsc *pdsc,
return -ENXIO;
}
wc.qcq = &pdsc->adminqcq;
index = __pdsc_adminq_post(pdsc, &pdsc->adminqcq, cmd, comp, &wc);
index = __pdsc_adminq_post(pdsc, &pdsc->adminqcq, cmd, comp);
if (index < 0) {
err = index;
goto err_out;
}
wc = &pdsc->adminqcq.q.info[index].completion;
time_start = jiffies;
time_limit = time_start + HZ * pdsc->devcmd_timeout;
do {
/* Timeslice the actual wait to catch IO errors etc early */
poll_jiffies = msecs_to_jiffies(poll_interval);
remaining = wait_for_completion_timeout(&wc.wait_completion,
poll_jiffies);
remaining = wait_for_completion_timeout(wc, poll_jiffies);
if (remaining)
break;
@@ -292,9 +282,11 @@ int pdsc_adminq_post(struct pdsc *pdsc,
dev_dbg(pdsc->dev, "%s: elapsed %d msecs\n",
__func__, jiffies_to_msecs(time_done - time_start));
/* Check the results */
if (time_after_eq(time_done, time_limit))
/* Check the results and clear an un-completed timeout */
if (time_after_eq(time_done, time_limit) && !completion_done(wc)) {
err = -ETIMEDOUT;
complete(wc);
}
dev_dbg(pdsc->dev, "read admin queue completion idx %d:\n", index);
dynamic_hex_dump("comp ", DUMP_PREFIX_OFFSET, 16, 1,
@@ -107,9 +107,6 @@ int pds_client_adminq_cmd(struct pds_auxiliary_dev *padev,
dev_dbg(pf->dev, "%s: %s opcode %d\n",
__func__, dev_name(&padev->aux_dev.dev), req->opcode);
if (pf->state)
return -ENXIO;
/* Wrap the client's request */
cmd.client_request.opcode = PDS_AQ_CMD_CLIENT_CMD;
cmd.client_request.client_id = cpu_to_le16(padev->client_id);
+4 -5
View File
@@ -167,8 +167,10 @@ static void pdsc_q_map(struct pdsc_queue *q, void *base, dma_addr_t base_pa)
q->base = base;
q->base_pa = base_pa;
for (i = 0, cur = q->info; i < q->num_descs; i++, cur++)
for (i = 0, cur = q->info; i < q->num_descs; i++, cur++) {
cur->desc = base + (i * q->desc_size);
init_completion(&cur->completion);
}
}
static void pdsc_cq_map(struct pdsc_cq *cq, void *base, dma_addr_t base_pa)
@@ -325,10 +327,7 @@ static int pdsc_core_init(struct pdsc *pdsc)
size_t sz;
int err;
/* Scale the descriptor ring length based on number of CPUs and VFs */
numdescs = max_t(int, PDSC_ADMINQ_MIN_LENGTH, num_online_cpus());
numdescs += 2 * pci_sriov_get_totalvfs(pdsc->pdev);
numdescs = roundup_pow_of_two(numdescs);
numdescs = PDSC_ADMINQ_MAX_LENGTH;
err = pdsc_qcq_alloc(pdsc, PDS_CORE_QTYPE_ADMINQ, 0, "adminq",
PDS_CORE_QCQ_F_CORE | PDS_CORE_QCQ_F_INTR,
numdescs,
+2 -2
View File
@@ -16,7 +16,7 @@
#define PDSC_WATCHDOG_SECS 5
#define PDSC_QUEUE_NAME_MAX_SZ 16
#define PDSC_ADMINQ_MIN_LENGTH 16 /* must be a power of two */
#define PDSC_ADMINQ_MAX_LENGTH 16 /* must be a power of two */
#define PDSC_NOTIFYQ_LENGTH 64 /* must be a power of two */
#define PDSC_TEARDOWN_RECOVERY false
#define PDSC_TEARDOWN_REMOVING true
@@ -96,7 +96,7 @@ struct pdsc_q_info {
unsigned int bytes;
unsigned int nbufs;
struct pdsc_buf_info bufs[PDS_CORE_MAX_FRAGS];
struct pdsc_wait_context *wc;
struct completion completion;
void *dest;
};
+1 -3
View File
@@ -105,7 +105,7 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
.fw_control.opcode = PDS_CORE_CMD_FW_CONTROL,
.fw_control.oper = PDS_CORE_FW_GET_LIST,
};
struct pds_core_fw_list_info fw_list;
struct pds_core_fw_list_info fw_list = {};
struct pdsc *pdsc = devlink_priv(dl);
union pds_core_dev_comp comp;
char buf[32];
@@ -118,8 +118,6 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
if (!err)
memcpy_fromio(&fw_list, pdsc->cmd_regs->data, sizeof(fw_list));
mutex_unlock(&pdsc->devcmd_lock);
if (err && err != -EIO)
return err;
listlen = min(fw_list.num_fw_slots, ARRAY_SIZE(fw_list.fw_names));
for (i = 0; i < listlen; i++) {
+28 -17
View File
@@ -1850,6 +1850,16 @@ static void enetc_xdp_drop(struct enetc_bdr *rx_ring, int rx_ring_first,
}
}
static void enetc_bulk_flip_buff(struct enetc_bdr *rx_ring, int rx_ring_first,
int rx_ring_last)
{
while (rx_ring_first != rx_ring_last) {
enetc_flip_rx_buff(rx_ring,
&rx_ring->rx_swbd[rx_ring_first]);
enetc_bdr_idx_inc(rx_ring, &rx_ring_first);
}
}
static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
struct napi_struct *napi, int work_limit,
struct bpf_prog *prog)
@@ -1868,11 +1878,10 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
while (likely(rx_frm_cnt < work_limit)) {
union enetc_rx_bd *rxbd, *orig_rxbd;
int orig_i, orig_cleaned_cnt;
struct xdp_buff xdp_buff;
struct sk_buff *skb;
int orig_i, err;
u32 bd_status;
int err;
rxbd = enetc_rxbd(rx_ring, i);
bd_status = le32_to_cpu(rxbd->r.lstatus);
@@ -1887,7 +1896,6 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
break;
orig_rxbd = rxbd;
orig_cleaned_cnt = cleaned_cnt;
orig_i = i;
enetc_build_xdp_buff(rx_ring, bd_status, &rxbd, &i,
@@ -1915,15 +1923,21 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
rx_ring->stats.xdp_drops++;
break;
case XDP_PASS:
rxbd = orig_rxbd;
cleaned_cnt = orig_cleaned_cnt;
i = orig_i;
skb = enetc_build_skb(rx_ring, bd_status, &rxbd,
&i, &cleaned_cnt,
ENETC_RXB_DMA_SIZE_XDP);
if (unlikely(!skb))
skb = xdp_build_skb_from_buff(&xdp_buff);
/* Probably under memory pressure, stop NAPI */
if (unlikely(!skb)) {
enetc_xdp_drop(rx_ring, orig_i, i);
rx_ring->stats.xdp_drops++;
goto out;
}
enetc_get_offloads(rx_ring, orig_rxbd, skb);
/* These buffers are about to be owned by the stack.
* Update our buffer cache (the rx_swbd array elements)
* with their other page halves.
*/
enetc_bulk_flip_buff(rx_ring, orig_i, i);
napi_gro_receive(napi, skb);
break;
@@ -1965,11 +1979,7 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
enetc_xdp_drop(rx_ring, orig_i, i);
rx_ring->stats.xdp_redirect_failures++;
} else {
while (orig_i != i) {
enetc_flip_rx_buff(rx_ring,
&rx_ring->rx_swbd[orig_i]);
enetc_bdr_idx_inc(rx_ring, &orig_i);
}
enetc_bulk_flip_buff(rx_ring, orig_i, i);
xdp_redirect_frm_cnt++;
rx_ring->stats.xdp_redirect++;
}
@@ -3362,7 +3372,8 @@ static int enetc_int_vector_init(struct enetc_ndev_priv *priv, int i,
bdr->buffer_offset = ENETC_RXB_PAD;
priv->rx_ring[i] = bdr;
err = xdp_rxq_info_reg(&bdr->xdp.rxq, priv->ndev, i, 0);
err = __xdp_rxq_info_reg(&bdr->xdp.rxq, priv->ndev, i, 0,
ENETC_RXB_DMA_SIZE_XDP);
if (err)
goto free_vector;
+20 -4
View File
@@ -4043,11 +4043,27 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset)
mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP);
if (mtk_is_netsys_v3_or_greater(eth)) {
/* PSE should not drop port1, port8 and port9 packets */
mtk_w32(eth, 0x00000302, PSE_DROP_CFG);
/* PSE dummy page mechanism */
mtk_w32(eth, PSE_DUMMY_WORK_GDM(1) | PSE_DUMMY_WORK_GDM(2) |
PSE_DUMMY_WORK_GDM(3) | DUMMY_PAGE_THR, PSE_DUMY_REQ);
/* PSE free buffer drop threshold */
mtk_w32(eth, 0x00600009, PSE_IQ_REV(8));
/* PSE should not drop port8, port9 and port13 packets from
* WDMA Tx
*/
mtk_w32(eth, 0x00002300, PSE_DROP_CFG);
/* PSE should drop packets to port8, port9 and port13 on WDMA Rx
* ring full
*/
mtk_w32(eth, 0x00002300, PSE_PPE_DROP(0));
mtk_w32(eth, 0x00002300, PSE_PPE_DROP(1));
mtk_w32(eth, 0x00002300, PSE_PPE_DROP(2));
/* GDM and CDM Threshold */
mtk_w32(eth, 0x00000707, MTK_CDMW0_THRES);
mtk_w32(eth, 0x08000707, MTK_CDMW0_THRES);
mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES);
/* Disable GDM1 RX CRC stripping */
@@ -4064,7 +4080,7 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset)
mtk_w32(eth, 0x00000300, PSE_DROP_CFG);
/* PSE should drop packets to port 8/9 on WDMA Rx ring full */
mtk_w32(eth, 0x00000300, PSE_PPE0_DROP);
mtk_w32(eth, 0x00000300, PSE_PPE_DROP(0));
/* PSE Free Queue Flow Control */
mtk_w32(eth, 0x01fa01f4, PSE_FQFC_CFG2);
+9 -1
View File
@@ -151,7 +151,15 @@
#define PSE_FQFC_CFG1 0x100
#define PSE_FQFC_CFG2 0x104
#define PSE_DROP_CFG 0x108
#define PSE_PPE0_DROP 0x110
#define PSE_PPE_DROP(x) (0x110 + ((x) * 0x4))
/* PSE Last FreeQ Page Request Control */
#define PSE_DUMY_REQ 0x10C
/* PSE_DUMY_REQ is not a typo but actually called like that also in
* MediaTek's datasheet
*/
#define PSE_DUMMY_WORK_GDM(x) BIT(16 + (x))
#define DUMMY_PAGE_THR 0x1
/* PSE Input Queue Reservation Register*/
#define PSE_IQ_REV(x) (0x140 + (((x) - 1) << 2))
@@ -637,10 +637,6 @@ struct mlx5_ttc_table *mlx5_create_inner_ttc_table(struct mlx5_core_dev *dev,
bool use_l4_type;
int err;
ttc = kvzalloc(sizeof(*ttc), GFP_KERNEL);
if (!ttc)
return ERR_PTR(-ENOMEM);
switch (params->ns_type) {
case MLX5_FLOW_NAMESPACE_PORT_SEL:
use_l4_type = MLX5_CAP_GEN_2(dev, pcc_ifa2) &&
@@ -654,7 +650,16 @@ struct mlx5_ttc_table *mlx5_create_inner_ttc_table(struct mlx5_core_dev *dev,
return ERR_PTR(-EINVAL);
}
ttc = kvzalloc(sizeof(*ttc), GFP_KERNEL);
if (!ttc)
return ERR_PTR(-ENOMEM);
ns = mlx5_get_flow_namespace(dev, params->ns_type);
if (!ns) {
kvfree(ttc);
return ERR_PTR(-EOPNOTSUPP);
}
groups = use_l4_type ? &inner_ttc_groups[TTC_GROUPS_USE_L4_TYPE] :
&inner_ttc_groups[TTC_GROUPS_DEFAULT];
@@ -710,10 +715,6 @@ struct mlx5_ttc_table *mlx5_create_ttc_table(struct mlx5_core_dev *dev,
bool use_l4_type;
int err;
ttc = kvzalloc(sizeof(*ttc), GFP_KERNEL);
if (!ttc)
return ERR_PTR(-ENOMEM);
switch (params->ns_type) {
case MLX5_FLOW_NAMESPACE_PORT_SEL:
use_l4_type = MLX5_CAP_GEN_2(dev, pcc_ifa2) &&
@@ -727,7 +728,16 @@ struct mlx5_ttc_table *mlx5_create_ttc_table(struct mlx5_core_dev *dev,
return ERR_PTR(-EINVAL);
}
ttc = kvzalloc(sizeof(*ttc), GFP_KERNEL);
if (!ttc)
return ERR_PTR(-ENOMEM);
ns = mlx5_get_flow_namespace(dev, params->ns_type);
if (!ns) {
kvfree(ttc);
return ERR_PTR(-EOPNOTSUPP);
}
groups = use_l4_type ? &ttc_groups[TTC_GROUPS_USE_L4_TYPE] :
&ttc_groups[TTC_GROUPS_DEFAULT];
@@ -320,8 +320,8 @@ enum rtc_control {
/* PTP and timestamping registers */
#define GMAC3_X_ATSNS GENMASK(19, 16)
#define GMAC3_X_ATSNS_SHIFT 16
#define GMAC3_X_ATSNS GENMASK(29, 25)
#define GMAC3_X_ATSNS_SHIFT 25
#define GMAC_PTP_TCR_ATSFC BIT(24)
#define GMAC_PTP_TCR_ATSEN0 BIT(25)
@@ -553,7 +553,7 @@ void dwmac1000_get_ptptime(void __iomem *ptpaddr, u64 *ptp_time)
u64 ns;
ns = readl(ptpaddr + GMAC_PTP_ATNR);
ns += readl(ptpaddr + GMAC_PTP_ATSR) * NSEC_PER_SEC;
ns += (u64)readl(ptpaddr + GMAC_PTP_ATSR) * NSEC_PER_SEC;
*ptp_time = ns;
}
@@ -222,7 +222,7 @@ static void get_ptptime(void __iomem *ptpaddr, u64 *ptp_time)
u64 ns;
ns = readl(ptpaddr + PTP_ATNR);
ns += readl(ptpaddr + PTP_ATSR) * NSEC_PER_SEC;
ns += (u64)readl(ptpaddr + PTP_ATSR) * NSEC_PER_SEC;
*ptp_time = ns;
}
+1 -1
View File
@@ -730,7 +730,7 @@ static int dp83822_phy_reset(struct phy_device *phydev)
return phydev->drv->config_init(phydev);
}
#ifdef CONFIG_OF_MDIO
#if IS_ENABLED(CONFIG_OF_MDIO)
static const u32 tx_amplitude_100base_tx_gain[] = {
80, 82, 83, 85, 87, 88, 90, 92,
93, 95, 97, 98, 100, 102, 103, 105,
+3 -43
View File
@@ -37,47 +37,6 @@ static int lan88xx_write_page(struct phy_device *phydev, int page)
return __phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, page);
}
static int lan88xx_phy_config_intr(struct phy_device *phydev)
{
int rc;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
/* unmask all source and clear them before enable */
rc = phy_write(phydev, LAN88XX_INT_MASK, 0x7FFF);
rc = phy_read(phydev, LAN88XX_INT_STS);
rc = phy_write(phydev, LAN88XX_INT_MASK,
LAN88XX_INT_MASK_MDINTPIN_EN_ |
LAN88XX_INT_MASK_LINK_CHANGE_);
} else {
rc = phy_write(phydev, LAN88XX_INT_MASK, 0);
if (rc)
return rc;
/* Ack interrupts after they have been disabled */
rc = phy_read(phydev, LAN88XX_INT_STS);
}
return rc < 0 ? rc : 0;
}
static irqreturn_t lan88xx_handle_interrupt(struct phy_device *phydev)
{
int irq_status;
irq_status = phy_read(phydev, LAN88XX_INT_STS);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}
if (!(irq_status & LAN88XX_INT_STS_LINK_CHANGE_))
return IRQ_NONE;
phy_trigger_machine(phydev);
return IRQ_HANDLED;
}
static int lan88xx_suspend(struct phy_device *phydev)
{
struct lan88xx_priv *priv = phydev->priv;
@@ -528,8 +487,9 @@ static struct phy_driver microchip_phy_driver[] = {
.config_aneg = lan88xx_config_aneg,
.link_change_notify = lan88xx_link_change_notify,
.config_intr = lan88xx_phy_config_intr,
.handle_interrupt = lan88xx_handle_interrupt,
/* Interrupt handling is broken, do not define related
* functions to force polling.
*/
.suspend = lan88xx_suspend,
.resume = genphy_resume,
+13 -10
View File
@@ -93,9 +93,8 @@ int phy_led_triggers_register(struct phy_device *phy)
if (!phy->phy_num_led_triggers)
return 0;
phy->led_link_trigger = devm_kzalloc(&phy->mdio.dev,
sizeof(*phy->led_link_trigger),
GFP_KERNEL);
phy->led_link_trigger = kzalloc(sizeof(*phy->led_link_trigger),
GFP_KERNEL);
if (!phy->led_link_trigger) {
err = -ENOMEM;
goto out_clear;
@@ -105,10 +104,9 @@ int phy_led_triggers_register(struct phy_device *phy)
if (err)
goto out_free_link;
phy->phy_led_triggers = devm_kcalloc(&phy->mdio.dev,
phy->phy_num_led_triggers,
sizeof(struct phy_led_trigger),
GFP_KERNEL);
phy->phy_led_triggers = kcalloc(phy->phy_num_led_triggers,
sizeof(struct phy_led_trigger),
GFP_KERNEL);
if (!phy->phy_led_triggers) {
err = -ENOMEM;
goto out_unreg_link;
@@ -129,11 +127,11 @@ int phy_led_triggers_register(struct phy_device *phy)
out_unreg:
while (i--)
phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
devm_kfree(&phy->mdio.dev, phy->phy_led_triggers);
kfree(phy->phy_led_triggers);
out_unreg_link:
phy_led_trigger_unregister(phy->led_link_trigger);
out_free_link:
devm_kfree(&phy->mdio.dev, phy->led_link_trigger);
kfree(phy->led_link_trigger);
phy->led_link_trigger = NULL;
out_clear:
phy->phy_num_led_triggers = 0;
@@ -147,8 +145,13 @@ void phy_led_triggers_unregister(struct phy_device *phy)
for (i = 0; i < phy->phy_num_led_triggers; i++)
phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
kfree(phy->phy_led_triggers);
phy->phy_led_triggers = NULL;
if (phy->led_link_trigger)
if (phy->led_link_trigger) {
phy_led_trigger_unregister(phy->led_link_trigger);
kfree(phy->led_link_trigger);
phy->led_link_trigger = NULL;
}
}
EXPORT_SYMBOL_GPL(phy_led_triggers_unregister);
+22 -16
View File
@@ -81,6 +81,7 @@ struct phylink {
unsigned int pcs_state;
bool link_failed;
bool suspend_link_up;
bool major_config_failed;
bool mac_supports_eee_ops;
bool mac_supports_eee;
@@ -2545,14 +2546,16 @@ void phylink_suspend(struct phylink *pl, bool mac_wol)
/* Stop the resolver bringing the link up */
__set_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state);
/* Disable the carrier, to prevent transmit timeouts,
* but one would hope all packets have been sent. This
* also means phylink_resolve() will do nothing.
*/
if (pl->netdev)
netif_carrier_off(pl->netdev);
else
pl->suspend_link_up = phylink_link_is_up(pl);
if (pl->suspend_link_up) {
/* Disable the carrier, to prevent transmit timeouts,
* but one would hope all packets have been sent. This
* also means phylink_resolve() will do nothing.
*/
if (pl->netdev)
netif_carrier_off(pl->netdev);
pl->old_link_state = false;
}
/* We do not call mac_link_down() here as we want the
* link to remain up to receive the WoL packets.
@@ -2603,15 +2606,18 @@ void phylink_resume(struct phylink *pl)
if (test_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state)) {
/* Wake-on-Lan enabled, MAC handling */
/* Call mac_link_down() so we keep the overall state balanced.
* Do this under the state_mutex lock for consistency. This
* will cause a "Link Down" message to be printed during
* resume, which is harmless - the true link state will be
* printed when we run a resolve.
*/
mutex_lock(&pl->state_mutex);
phylink_link_down(pl);
mutex_unlock(&pl->state_mutex);
if (pl->suspend_link_up) {
/* Call mac_link_down() so we keep the overall state
* balanced. Do this under the state_mutex lock for
* consistency. This will cause a "Link Down" message
* to be printed during resume, which is harmless -
* the true link state will be printed when we run a
* resolve.
*/
mutex_lock(&pl->state_mutex);
phylink_link_down(pl);
mutex_unlock(&pl->state_mutex);
}
/* Re-apply the link parameters so that all the settings get
* restored to the MAC.
+57 -12
View File
@@ -3342,7 +3342,8 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
static void virtnet_rx_pause(struct virtnet_info *vi, struct receive_queue *rq)
static void __virtnet_rx_pause(struct virtnet_info *vi,
struct receive_queue *rq)
{
bool running = netif_running(vi->dev);
@@ -3352,17 +3353,63 @@ static void virtnet_rx_pause(struct virtnet_info *vi, struct receive_queue *rq)
}
}
static void virtnet_rx_resume(struct virtnet_info *vi, struct receive_queue *rq)
static void virtnet_rx_pause_all(struct virtnet_info *vi)
{
int i;
/*
* Make sure refill_work does not run concurrently to
* avoid napi_disable race which leads to deadlock.
*/
disable_delayed_refill(vi);
cancel_delayed_work_sync(&vi->refill);
for (i = 0; i < vi->max_queue_pairs; i++)
__virtnet_rx_pause(vi, &vi->rq[i]);
}
static void virtnet_rx_pause(struct virtnet_info *vi, struct receive_queue *rq)
{
/*
* Make sure refill_work does not run concurrently to
* avoid napi_disable race which leads to deadlock.
*/
disable_delayed_refill(vi);
cancel_delayed_work_sync(&vi->refill);
__virtnet_rx_pause(vi, rq);
}
static void __virtnet_rx_resume(struct virtnet_info *vi,
struct receive_queue *rq,
bool refill)
{
bool running = netif_running(vi->dev);
if (!try_fill_recv(vi, rq, GFP_KERNEL))
if (refill && !try_fill_recv(vi, rq, GFP_KERNEL))
schedule_delayed_work(&vi->refill, 0);
if (running)
virtnet_napi_enable(rq);
}
static void virtnet_rx_resume_all(struct virtnet_info *vi)
{
int i;
enable_delayed_refill(vi);
for (i = 0; i < vi->max_queue_pairs; i++) {
if (i < vi->curr_queue_pairs)
__virtnet_rx_resume(vi, &vi->rq[i], true);
else
__virtnet_rx_resume(vi, &vi->rq[i], false);
}
}
static void virtnet_rx_resume(struct virtnet_info *vi, struct receive_queue *rq)
{
enable_delayed_refill(vi);
__virtnet_rx_resume(vi, rq, true);
}
static int virtnet_rx_resize(struct virtnet_info *vi,
struct receive_queue *rq, u32 ring_num)
{
@@ -5959,12 +6006,12 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
if (prog)
bpf_prog_add(prog, vi->max_queue_pairs - 1);
virtnet_rx_pause_all(vi);
/* Make sure NAPI is not using any XDP TX queues for RX. */
if (netif_running(dev)) {
for (i = 0; i < vi->max_queue_pairs; i++) {
virtnet_napi_disable(&vi->rq[i]);
for (i = 0; i < vi->max_queue_pairs; i++)
virtnet_napi_tx_disable(&vi->sq[i]);
}
}
if (!prog) {
@@ -5996,13 +6043,12 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
vi->xdp_enabled = false;
}
virtnet_rx_resume_all(vi);
for (i = 0; i < vi->max_queue_pairs; i++) {
if (old_prog)
bpf_prog_put(old_prog);
if (netif_running(dev)) {
virtnet_napi_enable(&vi->rq[i]);
if (netif_running(dev))
virtnet_napi_tx_enable(&vi->sq[i]);
}
}
return 0;
@@ -6014,11 +6060,10 @@ err:
rcu_assign_pointer(vi->rq[i].xdp_prog, old_prog);
}
virtnet_rx_resume_all(vi);
if (netif_running(dev)) {
for (i = 0; i < vi->max_queue_pairs; i++) {
virtnet_napi_enable(&vi->rq[i]);
for (i = 0; i < vi->max_queue_pairs; i++)
virtnet_napi_tx_enable(&vi->sq[i]);
}
}
if (prog)
bpf_prog_sub(prog, vi->max_queue_pairs - 1);
+13 -6
View File
@@ -985,20 +985,27 @@ static u32 xennet_run_xdp(struct netfront_queue *queue, struct page *pdata,
act = bpf_prog_run_xdp(prog, xdp);
switch (act) {
case XDP_TX:
get_page(pdata);
xdpf = xdp_convert_buff_to_frame(xdp);
err = xennet_xdp_xmit(queue->info->netdev, 1, &xdpf, 0);
if (unlikely(!err))
xdp_return_frame_rx_napi(xdpf);
else if (unlikely(err < 0))
if (unlikely(!xdpf)) {
trace_xdp_exception(queue->info->netdev, prog, act);
break;
}
get_page(pdata);
err = xennet_xdp_xmit(queue->info->netdev, 1, &xdpf, 0);
if (unlikely(err <= 0)) {
if (err < 0)
trace_xdp_exception(queue->info->netdev, prog, act);
xdp_return_frame_rx_napi(xdpf);
}
break;
case XDP_REDIRECT:
get_page(pdata);
err = xdp_do_redirect(queue->info->netdev, xdp, prog);
*need_xdp_flush = true;
if (unlikely(err))
if (unlikely(err)) {
trace_xdp_exception(queue->info->netdev, prog, act);
xdp_return_buff(xdp);
}
break;
case XDP_PASS:
case XDP_DROP:
+20 -11
View File
@@ -361,23 +361,29 @@ int mac_finish(struct phylink_config *config, unsigned int mode,
phy_interface_t iface);
/**
* mac_link_down() - take the link down
* mac_link_down() - notification that the link has gone down
* @config: a pointer to a &struct phylink_config.
* @mode: link autonegotiation mode
* @interface: link &typedef phy_interface_t mode
*
* If @mode is not an in-band negotiation mode (as defined by
* phylink_autoneg_inband()), force the link down and disable any
* Energy Efficient Ethernet MAC configuration. Interface type
* selection must be done in mac_config().
* Notifies the MAC that the link has gone down. This will not be called
* unless mac_link_up() has been previously called.
*
* The MAC should stop processing packets for transmission and reception.
* phylink will have called netif_carrier_off() to notify the networking
* stack that the link has gone down, so MAC drivers should not make this
* call.
*
* If @mode is %MLO_AN_INBAND, then this function must not prevent the
* link coming up.
*/
void mac_link_down(struct phylink_config *config, unsigned int mode,
phy_interface_t interface);
/**
* mac_link_up() - allow the link to come up
* mac_link_up() - notification that the link has come up
* @config: a pointer to a &struct phylink_config.
* @phy: any attached phy
* @phy: any attached phy (deprecated - please use LPI interfaces)
* @mode: link autonegotiation mode
* @interface: link &typedef phy_interface_t mode
* @speed: link speed
@@ -385,7 +391,10 @@ void mac_link_down(struct phylink_config *config, unsigned int mode,
* @tx_pause: link transmit pause enablement status
* @rx_pause: link receive pause enablement status
*
* Configure the MAC for an established link.
* Notifies the MAC that the link has come up, and the parameters of the
* link as seen from the MACs point of view. If mac_link_up() has been
* called previously, there will be an intervening call to mac_link_down()
* before this method will be subsequently called.
*
* @speed, @duplex, @tx_pause and @rx_pause indicate the finalised link
* settings, and should be used to configure the MAC block appropriately
@@ -397,9 +406,9 @@ void mac_link_down(struct phylink_config *config, unsigned int mode,
* that the user wishes to override the pause settings, and this should
* be allowed when considering the implementation of this method.
*
* If in-band negotiation mode is disabled, allow the link to come up. If
* @phy is non-%NULL, configure Energy Efficient Ethernet by calling
* phy_init_eee() and perform appropriate MAC configuration for EEE.
* Once configured, the MAC may begin to process packets for transmission
* and reception.
*
* Interface type selection must be done in mac_config().
*/
void mac_link_up(struct phylink_config *config, struct phy_device *phy,
+20 -6
View File
@@ -333,6 +333,8 @@ int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb)
struct dst_entry *dst;
int ret;
local_bh_disable();
if (dev_xmit_recursion()) {
net_crit_ratelimited("%s(): recursion limit reached on datapath\n",
__func__);
@@ -348,8 +350,10 @@ int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb)
lwtstate = dst->lwtstate;
if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
lwtstate->type > LWTUNNEL_ENCAP_MAX)
return 0;
lwtstate->type > LWTUNNEL_ENCAP_MAX) {
ret = 0;
goto out;
}
ret = -EOPNOTSUPP;
rcu_read_lock();
@@ -364,11 +368,13 @@ int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb)
if (ret == -EOPNOTSUPP)
goto drop;
return ret;
goto out;
drop:
kfree_skb(skb);
out:
local_bh_enable();
return ret;
}
EXPORT_SYMBOL_GPL(lwtunnel_output);
@@ -380,6 +386,8 @@ int lwtunnel_xmit(struct sk_buff *skb)
struct dst_entry *dst;
int ret;
local_bh_disable();
if (dev_xmit_recursion()) {
net_crit_ratelimited("%s(): recursion limit reached on datapath\n",
__func__);
@@ -396,8 +404,10 @@ int lwtunnel_xmit(struct sk_buff *skb)
lwtstate = dst->lwtstate;
if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
lwtstate->type > LWTUNNEL_ENCAP_MAX)
return 0;
lwtstate->type > LWTUNNEL_ENCAP_MAX) {
ret = 0;
goto out;
}
ret = -EOPNOTSUPP;
rcu_read_lock();
@@ -412,11 +422,13 @@ int lwtunnel_xmit(struct sk_buff *skb)
if (ret == -EOPNOTSUPP)
goto drop;
return ret;
goto out;
drop:
kfree_skb(skb);
out:
local_bh_enable();
return ret;
}
EXPORT_SYMBOL_GPL(lwtunnel_xmit);
@@ -428,6 +440,8 @@ int lwtunnel_input(struct sk_buff *skb)
struct dst_entry *dst;
int ret;
DEBUG_NET_WARN_ON_ONCE(!in_softirq());
if (dev_xmit_recursion()) {
net_crit_ratelimited("%s(): recursion limit reached on datapath\n",
__func__);
+6 -3
View File
@@ -861,14 +861,17 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
mutex_lock(&priv->lock);
err = 0;
netdev = netdev_get_by_index_lock(genl_info_net(info), ifindex);
if (!netdev || !netif_device_present(netdev)) {
if (!netdev) {
err = -ENODEV;
goto err_unlock_sock;
}
if (!netdev_need_ops_lock(netdev)) {
if (!netif_device_present(netdev))
err = -ENODEV;
else if (!netdev_need_ops_lock(netdev))
err = -EOPNOTSUPP;
if (err) {
NL_SET_BAD_ATTR(info->extack,
info->attrs[NETDEV_A_DEV_IFINDEX]);
goto err_unlock;
+13 -5
View File
@@ -100,10 +100,10 @@ static struct sk_buff *net_test_get_skb(struct net_device *ndev,
ehdr->h_proto = htons(ETH_P_IP);
if (attr->tcp) {
memset(thdr, 0, sizeof(*thdr));
thdr->source = htons(attr->sport);
thdr->dest = htons(attr->dport);
thdr->doff = sizeof(struct tcphdr) / 4;
thdr->check = 0;
} else {
uhdr->source = htons(attr->sport);
uhdr->dest = htons(attr->dport);
@@ -144,10 +144,18 @@ static struct sk_buff *net_test_get_skb(struct net_device *ndev,
attr->id = net_test_next_id;
shdr->id = net_test_next_id++;
if (attr->size)
skb_put(skb, attr->size);
if (attr->max_size && attr->max_size > skb->len)
skb_put(skb, attr->max_size - skb->len);
if (attr->size) {
void *payload = skb_put(skb, attr->size);
memset(payload, 0, attr->size);
}
if (attr->max_size && attr->max_size > skb->len) {
size_t pad_len = attr->max_size - skb->len;
void *pad = skb_put(skb, pad_len);
memset(pad, 0, pad_len);
}
skb->csum = 0;
skb->ip_summed = CHECKSUM_PARTIAL;
+5 -1
View File
@@ -337,7 +337,11 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
release_sock(sk);
sock_kfree_s(sk, match, sizeof(*match));
kfree_rcu_mightsleep(match);
/* Adjust sk_omem_alloc like sock_kfree_s() does, to match
* with allocation of this memory by sock_kmemdup()
*/
atomic_sub(sizeof(*match), &sk->sk_omem_alloc);
err = 0;
out:
+17 -6
View File
@@ -961,6 +961,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
if (cl != NULL) {
int old_flags;
int len = 0;
if (parentid) {
if (cl->cl_parent &&
@@ -991,9 +992,13 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
if (usc != NULL)
hfsc_change_usc(cl, usc, cur_time);
if (cl->qdisc->q.qlen != 0)
len = qdisc_peek_len(cl->qdisc);
/* Check queue length again since some qdisc implementations
* (e.g., netem/codel) might empty the queue during the peek
* operation.
*/
if (cl->qdisc->q.qlen != 0) {
int len = qdisc_peek_len(cl->qdisc);
if (cl->cl_flags & HFSC_RSC) {
if (old_flags & HFSC_RSC)
update_ed(cl, len);
@@ -1636,10 +1641,16 @@ hfsc_dequeue(struct Qdisc *sch)
if (cl->qdisc->q.qlen != 0) {
/* update ed */
next_len = qdisc_peek_len(cl->qdisc);
if (realtime)
update_ed(cl, next_len);
else
update_d(cl, next_len);
/* Check queue length again since some qdisc implementations
* (e.g., netem/codel) might empty the queue during the peek
* operation.
*/
if (cl->qdisc->q.qlen != 0) {
if (realtime)
update_ed(cl, next_len);
else
update_d(cl, next_len);
}
} else {
/* the class becomes passive */
eltree_remove(cl);
+2 -1
View File
@@ -716,7 +716,8 @@ void tipc_mon_reinit_self(struct net *net)
if (!mon)
continue;
write_lock_bh(&mon->lock);
mon->self->addr = tipc_own_addr(net);
if (mon->self)
mon->self->addr = tipc_own_addr(net);
write_unlock_bh(&mon->lock);
}
}
+2 -3
View File
@@ -206,9 +206,8 @@ chk_dump_one()
local token
local msg
ss_token="$(ss -inmHMN $ns | grep 'token:' |\
head -n 1 |\
sed 's/.*token:\([0-9a-f]*\).*/\1/')"
ss_token="$(ss -inmHMN $ns |
mptcp_lib_get_info_value "token" "token")"
token="$(ip netns exec $ns ./mptcp_diag -t $ss_token |\
awk -F':[ \t]+' '/^token/ {print $2}')"
@@ -313,5 +313,44 @@
"$TC qdisc del dev $DUMMY handle 1: root",
"$IP addr del 10.10.10.10/24 dev $DUMMY || true"
]
},
{
"id": "a4c3",
"name": "Test HFSC with netem/blackhole - queue emptying during peek operation",
"category": [
"qdisc",
"hfsc",
"netem",
"blackhole"
],
"plugins": {
"requires": "nsPlugin"
},
"setup": [
"$IP link set dev $DUMMY up || true",
"$IP addr add 10.10.10.10/24 dev $DUMMY || true",
"$TC qdisc add dev $DUMMY handle 1:0 root drr",
"$TC class add dev $DUMMY parent 1:0 classid 1:1 drr",
"$TC class add dev $DUMMY parent 1:0 classid 1:2 drr",
"$TC qdisc add dev $DUMMY parent 1:1 handle 2:0 plug limit 1024",
"$TC qdisc add dev $DUMMY parent 1:2 handle 3:0 hfsc default 1",
"$TC class add dev $DUMMY parent 3:0 classid 3:1 hfsc rt m1 5Mbit d 10ms m2 10Mbit",
"$TC qdisc add dev $DUMMY parent 3:1 handle 4:0 netem delay 1ms",
"$TC qdisc add dev $DUMMY parent 4:1 handle 5:0 blackhole",
"ping -c 3 -W 0.01 -i 0.001 -s 1 10.10.10.10 -I $DUMMY > /dev/null 2>&1 || true",
"$TC class change dev $DUMMY parent 3:0 classid 3:1 hfsc sc m1 5Mbit d 10ms m2 10Mbit",
"$TC class del dev $DUMMY parent 3:0 classid 3:1",
"$TC class add dev $DUMMY parent 3:0 classid 3:1 hfsc rt m1 5Mbit d 10ms m2 10Mbit",
"ping -c 3 -W 0.01 -i 0.001 -s 1 10.10.10.10 -I $DUMMY > /dev/null 2>&1 || true"
],
"cmdUnderTest": "$TC class change dev $DUMMY parent 3:0 classid 3:1 hfsc sc m1 5Mbit d 10ms m2 10Mbit",
"expExitCode": "0",
"verifyCmd": "$TC -s qdisc show dev $DUMMY",
"matchPattern": "qdisc hfsc 3:.*parent 1:2.*default 1",
"matchCount": "1",
"teardown": [
"$TC qdisc del dev $DUMMY handle 1:0 root",
"$IP addr del 10.10.10.10/24 dev $DUMMY || true"
]
}
]