Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Merge in late fixes in preparation for the net-next PR.

Conflicts:

net/tls/tls_sw.c
  406e8a651a ("net: skmsg: preserve sg.copy across SG transforms")
  79511603a6 ("tls: remove dead sockmap (psock) handling from the SW path")

drivers/net/ethernet/microsoft/mana/mana_en.c
  f8fd56977e ("net: mana: guard TX wq object destroy with INVALID_MANA_HANDLE check")
  d07efe5a6e ("net: mana: Use per-queue allocation for tx_qp to reduce allocation size")
https://lore.kernel.org/ajAPXu-C_PuTgV-a@sirena.org.uk

No adjacent changes.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski
2026-06-16 14:57:37 -07:00
63 changed files with 823 additions and 238 deletions

View File

@@ -402,6 +402,7 @@ Jesper Dangaard Brouer <hawk@kernel.org> <hawk@comx.dk>
Jesper Dangaard Brouer <hawk@kernel.org> <jbrouer@redhat.com>
Jesper Dangaard Brouer <hawk@kernel.org> <jdb@comx.dk>
Jesper Dangaard Brouer <hawk@kernel.org> <netoptimizer@brouer.com>
Jesse Brandeburg <jbrandeb@kernel.org> <jesse.brandeburg@intel.com>
Jessica Zhang <jesszhan0024@gmail.com> <jesszhan@codeaurora.org>
Jessica Zhang <jesszhan0024@gmail.com> <quic_jesszhan@quicinc.com>
Jessica Zhang <jesszhan0024@gmail.com> <jessica.zhang@oss.qualcomm.com>

View File

@@ -67,7 +67,7 @@ examples:
pinctrl-names = "default";
pinctrl-0 = <&eth0_pins>;
interrupt-parent = <&gpio>;
interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
local-mac-address = [04 05 06 01 02 03];
spi-max-frequency = <15000000>;
};

View File

@@ -429,7 +429,8 @@ qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int p
init_data.fwnode = led;
init_data.devname_mandatory = true;
init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d",
priv->internal_mdio_bus->id,
priv->internal_mdio_bus ?
priv->internal_mdio_bus->id : priv->bus->id,
port_num);
if (!init_data.devicename) {
fwnode_handle_put(led);

View File

@@ -361,7 +361,7 @@ static void airoha_fe_pse_ports_init(struct airoha_eth *eth)
PSE_QUEUE_RSV_PAGES);
/* PPE1 */
for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE1]; q++) {
if (q < pse_port_num_queues[FE_PSE_PORT_PPE1])
if (q < pse_port_num_queues[FE_PSE_PORT_PPE1] / 2)
airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE1, q,
PSE_QUEUE_RSV_PAGES);
else
@@ -1331,7 +1331,7 @@ static void airoha_qdma_init_qos_stats(struct airoha_qdma *qdma)
FIELD_PREP(CNTR_CHAN_MASK, i));
/* Tx-fwd transferred count */
airoha_qdma_wr(qdma, REG_CNTR_VAL((i << 1) + 1), 0);
airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1),
airoha_qdma_wr(qdma, REG_CNTR_CFG((i << 1) + 1),
CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK |
CNTR_ALL_DSCP_RING_EN_MASK |
FIELD_PREP(CNTR_SRC_MASK, 1) |

View File

@@ -1354,7 +1354,7 @@ static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe)
{
u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
struct airoha_foe_entry *hwe = ppe->foe;
int i, err = 0;
int i;
for (i = 0; i < sram_num_entries; i++) {
int err;
@@ -1362,10 +1362,10 @@ static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe)
memset(&hwe[i], 0, sizeof(*hwe));
err = airoha_ppe_foe_commit_sram_entry(ppe, i);
if (err)
break;
return err;
}
return err;
return 0;
}
static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth)

View File

@@ -121,8 +121,6 @@ static int airoha_ppe_debugfs_foe_show(struct seq_file *m, void *private,
case PPE_PKT_TYPE_IPV4_DSLITE:
src_port = &hwe->ipv4.new_tuple.src_port;
dest_port = &hwe->ipv4.new_tuple.dest_port;
fallthrough;
case PPE_PKT_TYPE_IPV4_ROUTE:
src_addr = &hwe->ipv4.new_tuple.src_ip;
dest_addr = &hwe->ipv4.new_tuple.dest_ip;
seq_puts(m, " new=");

View File

@@ -1011,6 +1011,7 @@ int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
mapping += bp->rx_dma_offset;
rx_buf->data = page;
rx_buf->data_ptr = page_address(page) + offset + bp->rx_offset;
rx_buf->offset = offset;
} else {
u8 *data = __bnxt_alloc_rx_frag(bp, &mapping, rxr, gfp);
@@ -1019,6 +1020,7 @@ int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
rx_buf->data = data;
rx_buf->data_ptr = data + bp->rx_offset;
rx_buf->offset = 0;
}
rx_buf->mapping = mapping;
@@ -1040,6 +1042,7 @@ void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons, void *data)
prod_rx_buf->data_ptr = cons_rx_buf->data_ptr;
prod_rx_buf->mapping = cons_rx_buf->mapping;
prod_rx_buf->offset = cons_rx_buf->offset;
prod_bd = &rxr->rx_desc_ring[RX_RING(bp, prod)][RX_IDX(prod)];
cons_bd = &rxr->rx_desc_ring[RX_RING(bp, cons)][RX_IDX(cons)];
@@ -1175,8 +1178,11 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp,
struct page *page = data;
u16 prod = rxr->rx_prod;
struct sk_buff *skb;
void *frag_start;
int err;
frag_start = page_address(page) + rxr->rx_buf_ring[cons].offset;
err = bnxt_alloc_rx_data(bp, rxr, prod, GFP_ATOMIC);
if (unlikely(err)) {
bnxt_reuse_rx_data(rxr, cons, data);
@@ -1185,13 +1191,13 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp,
dma_addr -= bp->rx_dma_offset;
dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr, rxr->rx_page_size,
bp->rx_dir);
skb = napi_build_skb(data_ptr - bp->rx_offset, rxr->rx_page_size);
skb = napi_build_skb(frag_start, rxr->rx_page_size);
if (!skb) {
page_pool_recycle_direct(rxr->page_pool, page);
return NULL;
}
skb_mark_for_recycle(skb);
skb_reserve(skb, bp->rx_offset);
skb_reserve(skb, data_ptr - (u8 *)frag_start);
__skb_put(skb, len);
return skb;

View File

@@ -911,6 +911,7 @@ struct bnxt_sw_rx_bd {
void *data;
u8 *data_ptr;
dma_addr_t mapping;
unsigned int offset;
};
struct bnxt_sw_rx_agg_bd {

View File

@@ -40,9 +40,8 @@
#include "bcmgenet.h"
/* Default highest priority queue for multi queue support */
#define GENET_Q1_PRIORITY 0
#define GENET_Q0_PRIORITY 1
#define GENET_Q0_WEIGHT 1
#define GENET_Q1_WEIGHT 4
#define GENET_Q0_RX_BD_CNT \
(TOTAL_DESC - priv->hw_params->rx_queues * priv->hw_params->rx_bds_per_q)
@@ -2126,13 +2125,6 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
int i;
index = skb_get_queue_mapping(skb);
/* Mapping strategy:
* queue_mapping = 0, unclassified, packet xmited through ring 0
* queue_mapping = 1, goes to ring 1. (highest priority queue)
* queue_mapping = 2, goes to ring 2.
* queue_mapping = 3, goes to ring 3.
* queue_mapping = 4, goes to ring 4.
*/
ring = &priv->tx_rings[index];
txq = netdev_get_tx_queue(dev, index);
@@ -2921,8 +2913,9 @@ static int bcmgenet_rdma_disable(struct bcmgenet_priv *priv)
/* Initialize Tx queues
*
* Queues 1-4 are priority-based, each one has 32 descriptors,
* with queue 1 being the highest priority queue.
* Queues 1-4 are the priority queues, each one has 32 descriptors.
* The weighted round-robin arbiter gives them a larger share of TX
* bandwidth than the default queue 0.
*
* Queue 0 is the default Tx queue with
* GENET_Q0_TX_BD_CNT = 256 - 4 * 32 = 128 descriptors.
@@ -2940,8 +2933,8 @@ static void bcmgenet_init_tx_queues(struct net_device *dev)
unsigned int start = 0, end = GENET_Q0_TX_BD_CNT;
u32 i, ring_mask, dma_priority[3] = {0, 0, 0};
/* Enable strict priority arbiter mode */
bcmgenet_tdma_writel(priv, DMA_ARBITER_SP, DMA_ARB_CTRL);
/* Enable Weighted Round-Robin arbiter mode */
bcmgenet_tdma_writel(priv, DMA_ARBITER_WRR, DMA_ARB_CTRL);
/* Initialize Tx priority queues */
for (i = 0; i <= priv->hw_params->tx_queues; i++) {
@@ -2949,7 +2942,7 @@ static void bcmgenet_init_tx_queues(struct net_device *dev)
start = end;
end += priv->hw_params->tx_bds_per_q;
dma_priority[DMA_PRIO_REG_INDEX(i)] |=
(i ? GENET_Q1_PRIORITY : GENET_Q0_PRIORITY)
(i ? GENET_Q1_WEIGHT : GENET_Q0_WEIGHT)
<< DMA_PRIO_REG_SHIFT(i);
}

View File

@@ -1572,13 +1572,15 @@ VIRTCHNL2_CHECK_STRUCT_LEN(16, virtchnl2_ptp_get_vport_tx_tstamp_latches);
* struct virtchnl2_ptp_get_dev_clk_time - Associated with message
* VIRTCHNL2_OP_PTP_GET_DEV_CLK_TIME.
* @dev_time_ns: Device clock time value in nanoseconds
* @pad: Padding for future extensions
*
* PF/VF sends this message to receive the time from the main timer.
*/
struct virtchnl2_ptp_get_dev_clk_time {
__le64 dev_time_ns;
u8 pad[8];
};
VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_ptp_get_dev_clk_time);
VIRTCHNL2_CHECK_STRUCT_LEN(16, virtchnl2_ptp_get_dev_clk_time);
/**
* struct virtchnl2_ptp_get_cross_time: Associated with message
@@ -1586,26 +1588,30 @@ VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_ptp_get_dev_clk_time);
* @sys_time_ns: System counter value expressed in nanoseconds, read
* synchronously with device time
* @dev_time_ns: Device clock time value expressed in nanoseconds
* @pad: Padding for future extensions
*
* PF/VF sends this message to receive the cross time.
*/
struct virtchnl2_ptp_get_cross_time {
__le64 sys_time_ns;
__le64 dev_time_ns;
u8 pad[8];
};
VIRTCHNL2_CHECK_STRUCT_LEN(16, virtchnl2_ptp_get_cross_time);
VIRTCHNL2_CHECK_STRUCT_LEN(24, virtchnl2_ptp_get_cross_time);
/**
* struct virtchnl2_ptp_set_dev_clk_time: Associated with message
* VIRTCHNL2_OP_PTP_SET_DEV_CLK_TIME.
* @dev_time_ns: Device time value expressed in nanoseconds to set
* @pad: Padding for future extensions
*
* PF/VF sends this message to set the time of the main timer.
*/
struct virtchnl2_ptp_set_dev_clk_time {
__le64 dev_time_ns;
u8 pad[8];
};
VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_ptp_set_dev_clk_time);
VIRTCHNL2_CHECK_STRUCT_LEN(16, virtchnl2_ptp_set_dev_clk_time);
/**
* struct virtchnl2_ptp_adj_dev_clk_fine: Associated with message

View File

@@ -2649,7 +2649,7 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
}
if (igc_fpe_is_pmac_enabled(adapter) &&
igc_fpe_handle_mpacket(adapter, rx_desc, size, pktbuf)) {
igc_fpe_handle_mpacket(adapter, rx_desc, size, pktbuf + pkt_offset)) {
/* Advance the ring next-to-clean */
igc_is_non_eop(rx_ring, rx_desc);
cleaned_count++;

View File

@@ -3958,7 +3958,8 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
}
/* initialize XPS */
if (!test_and_set_bit(__IXGBE_TX_XPS_INIT_DONE, ring->state)) {
if (!ring_is_xdp(ring) &&
!test_and_set_bit(__IXGBE_TX_XPS_INIT_DONE, ring->state)) {
struct ixgbe_q_vector *q_vector = ring->q_vector;
if (q_vector)

View File

@@ -283,31 +283,30 @@ M(NPC_GET_FIELD_HASH_INFO, 0x6013, npc_get_field_hash_info,
M(NPC_GET_FIELD_STATUS, 0x6014, npc_get_field_status, \
npc_get_field_status_req, \
npc_get_field_status_rsp) \
M(NPC_CN20K_MCAM_GET_FREE_COUNT, 0x6015, npc_cn20k_get_fcnt, \
msg_req, npc_cn20k_get_fcnt_rsp) \
M(NPC_CN20K_GET_KEX_CFG, 0x6016, npc_cn20k_get_kex_cfg, \
M(NPC_MCAM_DEFRAG, 0x6016, npc_defrag, \
msg_req, \
msg_rsp) \
M(NPC_CN20K_GET_KEX_CFG, 0x6017, npc_cn20k_get_kex_cfg, \
msg_req, npc_cn20k_get_kex_cfg_rsp) \
M(NPC_CN20K_MCAM_WRITE_ENTRY, 0x6017, npc_cn20k_mcam_write_entry, \
npc_cn20k_mcam_write_entry_req, msg_rsp) \
M(NPC_CN20K_MCAM_ALLOC_AND_WRITE_ENTRY, 0x6018, \
npc_cn20k_mcam_alloc_and_write_entry, \
M(NPC_CN20K_MCAM_GET_FREE_COUNT, 0x6018, npc_cn20k_get_fcnt, \
msg_req, npc_cn20k_get_fcnt_rsp) \
M(NPC_CN20K_MCAM_WRITE_ENTRY, 0x6019, npc_cn20k_mcam_write_entry, \
npc_cn20k_mcam_write_entry_req, msg_rsp) \
M(NPC_CN20K_MCAM_ALLOC_AND_WRITE_ENTRY, 0x601a, npc_cn20k_mcam_alloc_and_write_entry, \
npc_cn20k_mcam_alloc_and_write_entry_req, \
npc_mcam_alloc_and_write_entry_rsp) \
M(NPC_CN20K_MCAM_READ_ENTRY, 0x6019, npc_cn20k_mcam_read_entry, \
M(NPC_CN20K_MCAM_READ_ENTRY, 0x601b, npc_cn20k_mcam_read_entry, \
npc_mcam_read_entry_req, \
npc_cn20k_mcam_read_entry_rsp) \
M(NPC_CN20K_MCAM_READ_BASE_RULE, 0x601a, npc_cn20k_read_base_steer_rule, \
msg_req, npc_cn20k_mcam_read_base_rule_rsp) \
M(NPC_MCAM_DEFRAG, 0x601b, npc_defrag, \
msg_req, \
msg_rsp) \
M(NPC_MCAM_GET_NUM_KWS, 0x601c, npc_get_num_kws, \
M(NPC_CN20K_MCAM_READ_BASE_RULE, 0x601c, npc_cn20k_read_base_steer_rule, \
msg_req, npc_cn20k_mcam_read_base_rule_rsp) \
M(NPC_MCAM_GET_NUM_KWS, 0x601d, npc_get_num_kws, \
npc_get_num_kws_req, \
npc_get_num_kws_rsp) \
M(NPC_MCAM_GET_DFT_RL_IDXS, 0x601d, npc_get_dft_rl_idxs, \
M(NPC_MCAM_GET_DFT_RL_IDXS, 0x601e, npc_get_dft_rl_idxs, \
msg_req, \
npc_get_dft_rl_idxs_rsp)\
M(NPC_MCAM_GET_NPC_PFL_INFO, 0x601e, npc_get_pfl_info, \
M(NPC_MCAM_GET_NPC_PFL_INFO, 0x601f, npc_get_pfl_info, \
msg_req, \
npc_get_pfl_info_rsp) \
/* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \

View File

@@ -2476,7 +2476,7 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
/* Alloc memory for MCAM entry to counter mapping and for tracking
* counter's reference count.
*/
mcam->entry2cntr_map = kcalloc(mcam->bmap_entries, sizeof(u16),
mcam->entry2cntr_map = kcalloc(mcam->total_entries, sizeof(u16),
GFP_KERNEL);
if (!mcam->entry2cntr_map)
goto free_cntr_map;
@@ -2492,10 +2492,11 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
if (!mcam->entry2target_pffunc)
goto free_cntr_refcnt;
for (index = 0; index < mcam->bmap_entries; index++) {
for (index = 0; index < mcam->bmap_entries; index++)
mcam->entry2pfvf_map[index] = NPC_MCAM_INVALID_MAP;
for (index = 0; index < mcam->total_entries; index++)
mcam->entry2cntr_map[index] = NPC_MCAM_INVALID_MAP;
}
for (cntr = 0; cntr < mcam->counters.max; cntr++)
mcam->cntr2pfvf_map[cntr] = NPC_MCAM_INVALID_MAP;
@@ -3829,7 +3830,7 @@ static int __npc_mcam_free_counter(struct rvu *rvu,
struct msg_rsp *rsp)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
u16 index, entry = 0;
u16 index;
int blkaddr, err;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
@@ -3845,20 +3846,16 @@ static int __npc_mcam_free_counter(struct rvu *rvu,
mcam->cntr2pfvf_map[req->cntr] = NPC_MCAM_INVALID_MAP;
rvu_free_rsrc(&mcam->counters, req->cntr);
/* Disable all MCAM entry's stats which are using this counter */
while (entry < mcam->bmap_entries) {
/* Disable all MCAM entry's stats which are using this counter.
* Scan the full MCAM index range: AF-reserved rules (e.g. CPT pass-2)
*/
for (index = 0; index < mcam->total_entries; index++) {
if (!mcam->cntr_refcnt[req->cntr])
break;
index = find_next_bit(mcam->bmap, mcam->bmap_entries, entry);
if (index >= mcam->bmap_entries)
break;
entry = index + 1;
if (mcam->entry2cntr_map[index] != req->cntr)
continue;
npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
index, req->cntr);
npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr, index,
req->cntr);
}
return 0;
@@ -3929,7 +3926,7 @@ int rvu_mbox_handler_npc_mcam_unmap_counter(struct rvu *rvu,
struct npc_mcam_unmap_counter_req *req, struct msg_rsp *rsp)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
u16 index, entry = 0;
u16 index;
int blkaddr, rc;
/* Counter is not supported for CN20K */
@@ -3956,20 +3953,13 @@ int rvu_mbox_handler_npc_mcam_unmap_counter(struct rvu *rvu,
}
/* Disable all MCAM entry's stats which are using this counter */
while (entry < mcam->bmap_entries) {
for (index = 0; index < mcam->total_entries; index++) {
if (!mcam->cntr_refcnt[req->cntr])
break;
index = find_next_bit(mcam->bmap, mcam->bmap_entries, entry);
if (index >= mcam->bmap_entries)
break;
entry = index + 1;
if (mcam->entry2cntr_map[index] != req->cntr)
continue;
npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
index, req->cntr);
npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr, index,
req->cntr);
}
exit:
mutex_unlock(&mcam->lock);

View File

@@ -1118,9 +1118,16 @@ int otx2_register_mbox_intr(struct otx2_nic *pf, bool probe_af)
{
struct otx2_hw *hw = &pf->hw;
struct msg_req *req;
u64 mbox_int_mask;
char *irq_name;
int err;
mbox_int_mask = !is_cn20k(pf->pdev) ? BIT_ULL(0) :
BIT_ULL(0) | BIT_ULL(1);
/* Clear stale mailbox interrupt state before installing the handler. */
otx2_write64(pf, RVU_PF_INT, mbox_int_mask);
/* Register mailbox interrupt handler */
if (!is_cn20k(pf->pdev)) {
irq_name = &hw->irq_name[RVU_PF_INT_VEC_AFPF_MBOX * NAME_SIZE];
@@ -1146,17 +1153,8 @@ int otx2_register_mbox_intr(struct otx2_nic *pf, bool probe_af)
return err;
}
/* Enable mailbox interrupt for msgs coming from AF.
* First clear to avoid spurious interrupts, if any.
*/
if (!is_cn20k(pf->pdev)) {
otx2_write64(pf, RVU_PF_INT, BIT_ULL(0));
otx2_write64(pf, RVU_PF_INT_ENA_W1S, BIT_ULL(0));
} else {
otx2_write64(pf, RVU_PF_INT, BIT_ULL(0) | BIT_ULL(1));
otx2_write64(pf, RVU_PF_INT_ENA_W1S, BIT_ULL(0) |
BIT_ULL(1));
}
/* Enable mailbox interrupt for msgs coming from AF. */
otx2_write64(pf, RVU_PF_INT_ENA_W1S, mbox_int_mask);
if (!probe_af)
return 0;

View File

@@ -251,9 +251,17 @@ static int otx2vf_register_mbox_intr(struct otx2_nic *vf, bool probe_pf)
{
struct otx2_hw *hw = &vf->hw;
struct msg_req *req;
u64 mbox_int_mask;
char *irq_name;
int err;
mbox_int_mask = !is_cn20k(vf->pdev) ? BIT_ULL(0) :
BIT_ULL(0) | BIT_ULL(1) |
BIT_ULL(2) | BIT_ULL(3);
/* Clear stale mailbox interrupt state before installing the handler. */
otx2_write64(vf, RVU_VF_INT, mbox_int_mask);
/* Register mailbox interrupt handler */
irq_name = &hw->irq_name[RVU_VF_INT_VEC_MBOX * NAME_SIZE];
snprintf(irq_name, NAME_SIZE, "RVUVF%d AFVF Mbox", ((vf->pcifunc &
@@ -274,18 +282,8 @@ static int otx2vf_register_mbox_intr(struct otx2_nic *vf, bool probe_pf)
return err;
}
/* Enable mailbox interrupt for msgs coming from PF.
* First clear to avoid spurious interrupts, if any.
*/
if (!is_cn20k(vf->pdev)) {
otx2_write64(vf, RVU_VF_INT, BIT_ULL(0));
otx2_write64(vf, RVU_VF_INT_ENA_W1S, BIT_ULL(0));
} else {
otx2_write64(vf, RVU_VF_INT, BIT_ULL(0) | BIT_ULL(1) |
BIT_ULL(2) | BIT_ULL(3));
otx2_write64(vf, RVU_VF_INT_ENA_W1S, BIT_ULL(0) |
BIT_ULL(1) | BIT_ULL(2) | BIT_ULL(3));
}
/* Enable mailbox interrupt for msgs coming from PF. */
otx2_write64(vf, RVU_VF_INT_ENA_W1S, mbox_int_mask);
if (!probe_pf)
return 0;

View File

@@ -310,9 +310,9 @@ wed_amsdu_show(struct seq_file *s, void *data)
WED_AMSDU_ENG_MAX_QGPP_CNT),
DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(1),
WED_AMSDU_ENG_CUR_ENTRY),
DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2),
DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(1),
WED_AMSDU_ENG_MAX_BUF_MERGED),
DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2),
DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(1),
WED_AMSDU_ENG_MAX_MSDU_MERGED),
DUMP_STR("WED AMDSU ENG2 INFO"),
@@ -414,7 +414,7 @@ wed_amsdu_show(struct seq_file *s, void *data)
WED_AMSDU_ENG_CUR_ENTRY),
DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(7),
WED_AMSDU_ENG_MAX_BUF_MERGED),
DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4),
DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(7),
WED_AMSDU_ENG_MAX_MSDU_MERGED),
DUMP_STR("WED AMDSU ENG8 INFO"),

View File

@@ -367,8 +367,12 @@ mtk_wed_mcu_load_firmware(struct mtk_wed_wo *wo)
/* wo firmware reset */
wo_w32(MTK_WO_MCU_CFG_LS_WF_MCCR_CLR_ADDR, 0xc00);
val = wo_r32(MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR) |
MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK;
val = wo_r32(MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR);
if (!mtk_wed_is_v3_or_greater(wo->hw) && wo->hw->index)
val |= MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK;
else
val |= MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK;
wo_w32(MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val);
out:
release_firmware(fw);

View File

@@ -527,7 +527,6 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
{
struct mlx5_profile *prof = &dev->profile;
void *set_hca_cap;
int max_uc_list;
int err;
err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL);
@@ -613,10 +612,13 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
MLX5_SET(cmd_hca_cap, set_hca_cap, roce,
mlx5_is_roce_on(dev));
max_uc_list = max_uc_list_get_devlink_param(dev);
if (max_uc_list > 0)
MLX5_SET(cmd_hca_cap, set_hca_cap, log_max_current_uc_list,
ilog2(max_uc_list));
if (MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list)) {
int max_uc_list = max_uc_list_get_devlink_param(dev);
if (max_uc_list > 0)
MLX5_SET(cmd_hca_cap, set_hca_cap,
log_max_current_uc_list, ilog2(max_uc_list));
}
/* enable absolute native port num */
if (MLX5_CAP_GEN_MAX(dev, abs_native_port_num))

View File

@@ -1267,6 +1267,8 @@ int mana_gd_create_mana_wq_cq(struct gdma_dev *gd,
if (!queue)
return -ENOMEM;
queue->id = INVALID_QUEUE_ID;
gmi = &queue->mem_info;
err = mana_gd_alloc_memory(gc, spec->queue_size, gmi);
if (err) {

View File

@@ -2401,7 +2401,9 @@ static void mana_destroy_txq(struct mana_port_context *apc)
netif_napi_del_locked(napi);
apc->tx_qp[i]->txq.napi_initialized = false;
}
mana_destroy_wq_obj(apc, GDMA_SQ, apc->tx_qp[i]->tx_object);
if (apc->tx_qp[i]->tx_object != INVALID_MANA_HANDLE)
mana_destroy_wq_obj(apc, GDMA_SQ, apc->tx_qp[i]->tx_object);
mana_deinit_cq(apc, &apc->tx_qp[i]->tx_cq);

View File

@@ -7,6 +7,7 @@
#include <linux/bitfield.h>
#include <linux/iopoll.h>
#include <linux/interrupt.h>
#include <linux/mdio.h>
#include <linux/phy.h>
#include <linux/oa_tc6.h>
@@ -44,6 +45,8 @@
#define INT_MASK0_LOSS_OF_FRAME_ERR_MASK BIT(4)
#define INT_MASK0_RX_BUFFER_OVERFLOW_ERR_MASK BIT(3)
#define INT_MASK0_TX_PROTOCOL_ERR_MASK BIT(0)
#define INT_MASK0_ALL_INTERRUPTS (GENMASK(5, 0) | \
GENMASK(12, 7))
/* PHY Clause 22 registers base address and mask */
#define OA_TC6_PHY_STD_REG_ADDR_BASE 0xFF00
@@ -107,7 +110,6 @@
/* Internal structure for MAC-PHY drivers */
struct oa_tc6 {
struct device *dev;
struct net_device *netdev;
struct phy_device *phydev;
struct mii_bus *mdiobus;
@@ -121,14 +123,13 @@ struct oa_tc6 {
struct sk_buff *ongoing_tx_skb;
struct sk_buff *waiting_tx_skb;
struct sk_buff *rx_skb;
struct task_struct *spi_thread;
wait_queue_head_t spi_wq;
u16 tx_skb_offset;
u16 spi_data_tx_buf_offset;
u16 tx_credits;
u8 rx_chunks_available;
bool rx_buf_overflow;
bool int_flag;
bool disable_traffic;
};
enum oa_tc6_header_type {
@@ -518,7 +519,7 @@ static int oa_tc6_mdiobus_register(struct oa_tc6 *tc6)
tc6->mdiobus->read_c45 = oa_tc6_mdiobus_read_c45;
tc6->mdiobus->write_c45 = oa_tc6_mdiobus_write_c45;
tc6->mdiobus->name = "oa-tc6-mdiobus";
tc6->mdiobus->parent = tc6->dev;
tc6->mdiobus->parent = &tc6->spi->dev;
snprintf(tc6->mdiobus->id, ARRAY_SIZE(tc6->mdiobus->id), "%s",
dev_name(&tc6->spi->dev));
@@ -669,6 +670,38 @@ static void oa_tc6_cleanup_ongoing_tx_skb(struct oa_tc6 *tc6)
}
}
static void oa_tc6_cleanup_waiting_tx_skb(struct oa_tc6 *tc6)
{
if (tc6->waiting_tx_skb) {
tc6->netdev->stats.tx_dropped++;
kfree_skb(tc6->waiting_tx_skb);
tc6->waiting_tx_skb = NULL;
}
}
static void oa_tc6_free_pending_skbs(struct oa_tc6 *tc6)
{
oa_tc6_cleanup_ongoing_tx_skb(tc6);
oa_tc6_cleanup_ongoing_rx_skb(tc6);
oa_tc6_cleanup_waiting_tx_skb(tc6);
}
/* If the failure is at SPI interface level, masking and clearing
* the interrupt of the device won't work. Since SPI interrupt is
* disabled, it should stop the repeated interrupts.
*/
static void oa_tc6_disable_traffic(struct oa_tc6 *tc6)
{
u32 regval = INT_MASK0_ALL_INTERRUPTS;
tc6->disable_traffic = true;
oa_tc6_free_pending_skbs(tc6);
oa_tc6_write_register(tc6, OA_TC6_REG_INT_MASK0, regval);
oa_tc6_read_register(tc6, OA_TC6_REG_STATUS0, &regval);
oa_tc6_write_register(tc6, OA_TC6_REG_STATUS0, regval);
dev_err(&tc6->spi->dev, "Device interrupt disabled to avoid interrupt storm");
}
static int oa_tc6_process_extended_status(struct oa_tc6 *tc6)
{
u32 value;
@@ -752,6 +785,17 @@ static int oa_tc6_process_rx_chunk_footer(struct oa_tc6 *tc6, u32 footer)
static void oa_tc6_submit_rx_skb(struct oa_tc6 *tc6)
{
/* MAC-PHY delivers each frame with its Ethernet FCS attached.
* Strip it before handing over to the stack, unless the user
* has asked to keep it via NETIF_F_RXFCS. Keeping the FCS
* in the frame is harmless for IP traffic, but is parsed as
* a (malformed) suffix TLV by PTP, which makes ptp4l reject
* every message with "bad message" error.
*/
if (!(tc6->netdev->features & NETIF_F_RXFCS) &&
tc6->rx_skb->len > ETH_FCS_LEN)
skb_trim(tc6->rx_skb, tc6->rx_skb->len - ETH_FCS_LEN);
tc6->rx_skb->protocol = eth_type_trans(tc6->rx_skb, tc6->netdev);
tc6->netdev->stats.rx_packets++;
tc6->netdev->stats.rx_bytes += tc6->rx_skb->len;
@@ -1105,29 +1149,29 @@ static int oa_tc6_try_spi_transfer(struct oa_tc6 *tc6)
return 0;
}
static int oa_tc6_spi_thread_handler(void *data)
static irqreturn_t oa_tc6_macphy_threaded_irq(int irq, void *data)
{
struct oa_tc6 *tc6 = data;
int ret;
int ret = 0;
while (likely(!kthread_should_stop())) {
/* This kthread will be waken up if there is a tx skb or mac-phy
* interrupt to perform spi transfer with tx chunks.
*/
wait_event_interruptible(tc6->spi_wq, tc6->int_flag ||
(tc6->waiting_tx_skb &&
tc6->tx_credits) ||
kthread_should_stop());
if (kthread_should_stop())
break;
ret = oa_tc6_try_spi_transfer(tc6);
if (ret)
return ret;
/* It is possible that interrupt woke the thread before it is
* disabled. Until we come up with good recovery mechanism,
* no need to attempt spi transfer, once it fails. Pending skbs
* are already freed.
*/
if (!tc6->disable_traffic) {
while (tc6->int_flag ||
(tc6->waiting_tx_skb && tc6->tx_credits)) {
ret = oa_tc6_try_spi_transfer(tc6);
if (ret) {
disable_irq_nosync(tc6->spi->irq);
oa_tc6_disable_traffic(tc6);
break;
}
}
}
return 0;
return IRQ_HANDLED;
}
static int oa_tc6_update_buffer_status_from_register(struct oa_tc6 *tc6)
@@ -1161,11 +1205,15 @@ static irqreturn_t oa_tc6_macphy_isr(int irq, void *data)
* the previous rx footer.
* - extended status event not reported in the previous rx footer.
*/
tc6->int_flag = true;
/* Wake spi kthread to perform spi transfer */
wake_up_interruptible(&tc6->spi_wq);
return IRQ_HANDLED;
if (tc6->disable_traffic)
disable_irq_nosync(tc6->spi->irq);
else
tc6->int_flag = true;
/* Wake IRQ thread to perform spi transfer . In case
* disable_traffic is set, threaded irq may run again
* one more time.
*/
return IRQ_WAKE_THREAD;
}
/**
@@ -1202,7 +1250,7 @@ EXPORT_SYMBOL_GPL(oa_tc6_zero_align_receive_frame_enable);
*/
netdev_tx_t oa_tc6_start_xmit(struct oa_tc6 *tc6, struct sk_buff *skb)
{
if (tc6->waiting_tx_skb) {
if (tc6->disable_traffic || tc6->waiting_tx_skb) {
netif_stop_queue(tc6->netdev);
return NETDEV_TX_BUSY;
}
@@ -1217,8 +1265,8 @@ netdev_tx_t oa_tc6_start_xmit(struct oa_tc6 *tc6, struct sk_buff *skb)
tc6->waiting_tx_skb = skb;
spin_unlock_bh(&tc6->tx_skb_lock);
/* Wake spi kthread to perform spi transfer */
wake_up_interruptible(&tc6->spi_wq);
/* Wake the threaded IRQ to perform spi transfer. */
irq_wake_thread(tc6->spi->irq, tc6);
return NETDEV_TX_OK;
}
@@ -1311,24 +1359,15 @@ struct oa_tc6 *oa_tc6_init(struct spi_device *spi, struct net_device *netdev)
goto phy_exit;
}
init_waitqueue_head(&tc6->spi_wq);
tc6->spi_thread = kthread_run(oa_tc6_spi_thread_handler, tc6,
"oa-tc6-spi-thread");
if (IS_ERR(tc6->spi_thread)) {
dev_err(&tc6->spi->dev, "Failed to create SPI thread\n");
goto phy_exit;
}
sched_set_fifo(tc6->spi_thread);
ret = devm_request_irq(&tc6->spi->dev, tc6->spi->irq, oa_tc6_macphy_isr,
IRQF_TRIGGER_FALLING, dev_name(&tc6->spi->dev),
tc6);
ret = devm_request_threaded_irq(&tc6->spi->dev, tc6->spi->irq,
oa_tc6_macphy_isr,
oa_tc6_macphy_threaded_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
dev_name(&tc6->spi->dev), tc6);
if (ret) {
dev_err(&tc6->spi->dev, "Failed to request macphy isr %d\n",
ret);
goto kthread_stop;
goto phy_exit;
}
/* oa_tc6_sw_reset_macphy() function resets and clears the MAC-PHY reset
@@ -1338,12 +1377,10 @@ struct oa_tc6 *oa_tc6_init(struct spi_device *spi, struct net_device *netdev)
* 7.7 and 9.2.8.8 in the OPEN Alliance specification for more details.
*/
tc6->int_flag = true;
wake_up_interruptible(&tc6->spi_wq);
irq_wake_thread(tc6->spi->irq, tc6);
return tc6;
kthread_stop:
kthread_stop(tc6->spi_thread);
phy_exit:
oa_tc6_phy_exit(tc6);
return NULL;
@@ -1356,11 +1393,10 @@ EXPORT_SYMBOL_GPL(oa_tc6_init);
*/
void oa_tc6_exit(struct oa_tc6 *tc6)
{
tc6->disable_traffic = true;
disable_irq(tc6->spi->irq);
oa_tc6_phy_exit(tc6);
kthread_stop(tc6->spi_thread);
dev_kfree_skb_any(tc6->ongoing_tx_skb);
dev_kfree_skb_any(tc6->waiting_tx_skb);
dev_kfree_skb_any(tc6->rx_skb);
oa_tc6_free_pending_skbs(tc6);
}
EXPORT_SYMBOL_GPL(oa_tc6_exit);

View File

@@ -105,6 +105,7 @@ static int emac_xsk_xmit_zc(struct prueth_emac *emac,
struct xdp_desc xdp_desc;
int num_tx = 0, pkt_len;
int descs_avail, ret;
u32 dst_tag_id;
u32 *epib;
int i;
@@ -137,9 +138,17 @@ static int emac_xsk_xmit_zc(struct prueth_emac *emac,
epib[0] = 0;
epib[1] = 0;
cppi5_hdesc_set_pktlen(host_desc, pkt_len);
cppi5_desc_set_tags_ids(&host_desc->hdr, 0,
(emac->port_id | (q_idx << 8)));
dst_tag_id = emac->port_id | (q_idx << 8);
if (emac->prueth->is_hsr_offload_mode &&
(ndev->features & NETIF_F_HW_HSR_DUP))
dst_tag_id = PRUETH_UNDIRECTED_PKT_DST_TAG;
if (emac->prueth->is_hsr_offload_mode &&
(ndev->features & NETIF_F_HW_HSR_TAG_INS))
epib[1] |= PRUETH_UNDIRECTED_PKT_TAG_INS;
cppi5_desc_set_tags_ids(&host_desc->hdr, 0, dst_tag_id);
k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &dma_buf);
cppi5_hdesc_attach_buf(host_desc, dma_buf, pkt_len, dma_buf,
pkt_len);
@@ -696,6 +705,7 @@ u32 emac_xmit_xdp_frame(struct prueth_emac *emac,
dma_addr_t desc_dma, buf_dma;
struct prueth_swdata *swdata;
struct page *page;
u32 dst_tag_id;
u32 *epib;
int ret;
@@ -737,9 +747,25 @@ u32 emac_xmit_xdp_frame(struct prueth_emac *emac,
/* set dst tag to indicate internal qid at the firmware which is at
* bit8..bit15. bit0..bit7 indicates port num for directed
* packets in case of switch mode operation
* packets in case of switch mode operation and port num 0
* for undirected packets in case of HSR offload mode.
*
* XDP_TX frames arrive on a slave port with the HSR tag already
* stripped by the PRU firmware. Like skb TX via hsr0, they must
* be sent as undirected so the PRU duplicates them to both ports
* and re-inserts the HSR sequence tag.
*/
cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8)));
dst_tag_id = emac->port_id | (q_idx << 8);
if (emac->prueth->is_hsr_offload_mode &&
(ndev->features & NETIF_F_HW_HSR_DUP))
dst_tag_id = PRUETH_UNDIRECTED_PKT_DST_TAG;
if (emac->prueth->is_hsr_offload_mode &&
(ndev->features & NETIF_F_HW_HSR_TAG_INS))
epib[1] |= PRUETH_UNDIRECTED_PKT_TAG_INS;
cppi5_desc_set_tags_ids(&first_desc->hdr, 0, dst_tag_id);
k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma);
cppi5_hdesc_attach_buf(first_desc, buf_dma, xdpf->len, buf_dma, xdpf->len);
swdata = cppi5_hdesc_get_swdata(first_desc);
@@ -927,6 +953,7 @@ static int emac_rx_packet_zc(struct prueth_emac *emac, u32 flow_id,
struct cppi5_host_desc_t *desc_rx;
struct prueth_swdata *swdata;
dma_addr_t desc_dma, buf_dma;
int avail_desc, alloc_budget;
struct xdp_buff *xdp;
int xdp_status = 0;
int count = 0;
@@ -993,16 +1020,13 @@ static int emac_rx_packet_zc(struct prueth_emac *emac, u32 flow_id,
if (xdp_status & ICSSG_XDP_REDIR)
xdp_do_flush();
/* Allocate xsk buffers from the pool for the "count" number of
* packets processed in order to be able to receive more packets.
*/
ret = prueth_rx_alloc_zc(emac, count);
avail_desc = k3_cppi_desc_pool_avail(rx_chn->desc_pool);
alloc_budget = min_t(int, budget, avail_desc);
ret = prueth_rx_alloc_zc(emac, alloc_budget);
if (xsk_uses_need_wakeup(rx_chn->xsk_pool)) {
/* If the user space doesn't provide enough buffers then it must
* explicitly wake up the kernel when new buffers are available
*/
if (ret < count)
if (ret < alloc_budget)
xsk_set_rx_need_wakeup(rx_chn->xsk_pool);
else
xsk_clear_rx_need_wakeup(rx_chn->xsk_pool);

View File

@@ -148,6 +148,7 @@ static void pfcp_link_setup(struct net_device *dev)
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
dev->priv_flags |= IFF_NO_QUEUE;
dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
netif_keep_dst(dev);
}

View File

@@ -6222,6 +6222,19 @@ static void virtnet_free_irq_moder(struct virtnet_info *vi)
rtnl_unlock();
}
static netdev_features_t virtnet_features_check(struct sk_buff *skb,
struct net_device *dev,
netdev_features_t features)
{
/* Inner csum offload is only available for GSO packets. */
if (skb->encapsulation &&
(!skb_is_gso(skb) || netif_needs_gso(skb, features)))
return features & ~NETIF_F_CSUM_MASK;
/* Passthru. */
return features;
}
static const struct net_device_ops virtnet_netdev = {
.ndo_open = virtnet_open,
.ndo_stop = virtnet_close,
@@ -6235,7 +6248,7 @@ static const struct net_device_ops virtnet_netdev = {
.ndo_bpf = virtnet_xdp,
.ndo_xdp_xmit = virtnet_xdp_xmit,
.ndo_xsk_wakeup = virtnet_xsk_wakeup,
.ndo_features_check = passthru_features_check,
.ndo_features_check = virtnet_features_check,
.ndo_get_phys_port_name = virtnet_get_phys_port_name,
.ndo_set_features = virtnet_set_features,
.ndo_tx_timeout = virtnet_tx_timeout,

View File

@@ -106,6 +106,8 @@ static int t7xx_port_ctrl_tx(struct t7xx_port *port, struct sk_buff *skb)
while (cur) {
cloned = skb_clone(cur, GFP_KERNEL);
if (!cloned)
return cnt ? cnt : -ENOMEM;
cloned->len = skb_headlen(cur);
ret = t7xx_port_send_skb(port, cloned, 0, 0);
if (ret) {

View File

@@ -127,6 +127,7 @@ void afs_close_socket(struct afs_net *net)
{
_enter("");
cancel_work_sync(&net->charge_preallocation_work);
kernel_listen(net->socket, 0);
flush_workqueue(afs_async_calls);
@@ -742,7 +743,7 @@ void afs_charge_preallocation(struct work_struct *work)
container_of(work, struct afs_net, charge_preallocation_work);
struct afs_call *call = net->spare_incoming_call;
for (;;) {
while (READ_ONCE(net->live)) {
if (!call) {
call = afs_alloc_call(net, &afs_RXCMxxxx, GFP_KERNEL);
if (!call)
@@ -792,7 +793,8 @@ static void afs_rx_new_call(struct sock *sk, struct rxrpc_call *rxcall,
if (!call->server)
trace_afs_cm_no_server(call, rxrpc_kernel_remote_srx(call->peer));
queue_work(afs_wq, &net->charge_preallocation_work);
if (net->live)
queue_work(afs_wq, &net->charge_preallocation_work);
}
/*

View File

@@ -1993,6 +1993,8 @@ enum netdev_reg_state {
* @qdisc_hash: qdisc hash table
* @watchdog_timeo: Represents the timeout that is used by
* the watchdog (see dev_watchdog())
* @watchdog_lock: protect watchdog_ref_held
* @watchdog_ref_held: True if the watchdog device ref is taken.
* @watchdog_timer: List of timers
*
* @proto_down_reason: reason a netdev interface is held down
@@ -2404,6 +2406,8 @@ struct net_device {
/* These may be needed for future network-power-down code. */
struct timer_list watchdog_timer;
int watchdog_timeo;
spinlock_t watchdog_lock;
bool watchdog_ref_held;
u32 proto_down_reason;

View File

@@ -4,6 +4,7 @@
#ifndef _LINUX_SKMSG_H
#define _LINUX_SKMSG_H
#include <linux/bitops.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/scatterlist.h>
@@ -199,11 +200,14 @@ static inline void sk_msg_xfer(struct sk_msg *dst, struct sk_msg *src,
int which, u32 size)
{
dst->sg.data[which] = src->sg.data[which];
__assign_bit(which, dst->sg.copy, test_bit(which, src->sg.copy));
dst->sg.data[which].length = size;
dst->sg.size += size;
src->sg.size -= size;
src->sg.data[which].length -= size;
src->sg.data[which].offset += size;
if (!src->sg.data[which].length)
__clear_bit(which, src->sg.copy);
}
static inline void sk_msg_xfer_full(struct sk_msg *dst, struct sk_msg *src)
@@ -273,16 +277,19 @@ static inline void sk_msg_page_add(struct sk_msg *msg, struct page *page,
static inline void sk_msg_sg_copy(struct sk_msg *msg, u32 i, bool copy_state)
{
do {
if (copy_state)
__set_bit(i, msg->sg.copy);
else
__clear_bit(i, msg->sg.copy);
__assign_bit(i, msg->sg.copy, copy_state);
sk_msg_iter_var_next(i);
if (i == msg->sg.end)
break;
} while (1);
}
static inline void sk_msg_sg_copy_assign(struct sk_msg *dst, u32 dst_i,
const struct sk_msg *src, u32 src_i)
{
__assign_bit(dst_i, dst->sg.copy, test_bit(src_i, src->sg.copy));
}
static inline void sk_msg_sg_copy_set(struct sk_msg *msg, u32 start)
{
sk_msg_sg_copy(msg, start, true);

View File

@@ -111,6 +111,11 @@ static inline void fib_rule_get(struct fib_rule *rule)
refcount_inc(&rule->refcnt);
}
static inline bool fib_rule_get_safe(struct fib_rule *rule)
{
return refcount_inc_not_zero(&rule->refcnt);
}
static inline void fib_rule_put(struct fib_rule *rule)
{
if (refcount_dec_and_test(&rule->refcnt))

View File

@@ -628,6 +628,11 @@ static inline void fib_info_hold(struct fib_info *fi)
refcount_inc(&fi->fib_clntref);
}
static inline bool fib_info_hold_safe(struct fib_info *fi)
{
return refcount_inc_not_zero(&fi->fib_clntref);
}
static inline void fib_info_put(struct fib_info *fi)
{
if (refcount_dec_and_test(&fi->fib_clntref))

View File

@@ -2925,6 +2925,11 @@ static inline int tcp_call_bpf_3arg(struct sock *sk, int op, u32 arg1, u32 arg2,
return tcp_call_bpf(sk, op, 3, args);
}
static inline void tcp_clear_sock_ops_cb_flags(struct sock *sk)
{
tcp_sk(sk)->bpf_sock_ops_cb_flags = 0;
}
#else
static inline int tcp_call_bpf(struct sock *sk, int op, u32 nargs, u32 *args)
{
@@ -2942,6 +2947,10 @@ static inline int tcp_call_bpf_3arg(struct sock *sk, int op, u32 arg1, u32 arg2,
return -EPERM;
}
static inline void tcp_clear_sock_ops_cb_flags(struct sock *sk)
{
}
#endif
static inline u32 tcp_timeout_init(struct sock *sk)

View File

@@ -117,9 +117,9 @@ int lowpan_nhc_do_uncompression(struct sk_buff *skb,
return ret;
}
} else {
spin_unlock_bh(&lowpan_nhc_lock);
netdev_warn(dev, "received nhc id for %s which is not implemented.\n",
nhc->name);
spin_unlock_bh(&lowpan_nhc_lock);
return -ENOTSUPP;
}
} else {

View File

@@ -670,6 +670,8 @@ __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
static int check_tp(const struct atm_trafprm *tp)
{
/* @@@ Should be merged with adjust_tp */
if (tp->traffic_class > ATM_ANYCLASS)
return -EINVAL;
if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS)
return 0;
if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr &&

View File

@@ -805,6 +805,12 @@ int br_cfm_cc_ccm_tx(struct net_bridge *br, const u32 instance,
goto save;
}
if (!interval_to_us(mep->cc_config.exp_interval)) {
NL_SET_ERR_MSG_MOD(extack,
"Invalid CCM interval");
return -EINVAL;
}
/* Start delayed work to transmit CCM frames. It is done with zero delay
* to send first frame immediately
*/

View File

@@ -34,7 +34,9 @@ br_cfm_cc_config_policy[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1] = {
[IFLA_BRIDGE_CFM_CC_CONFIG_UNSPEC] = { .type = NLA_REJECT },
[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE] = { .type = NLA_U32 },
[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE] = { .type = NLA_U32 },
[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] = { .type = NLA_U32 },
[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] =
NLA_POLICY_RANGE(NLA_U32, BR_CFM_CCM_INTERVAL_3_3_MS,
BR_CFM_CCM_INTERVAL_10_MIN),
[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID] = {
.type = NLA_BINARY, .len = CFM_MAID_LENGTH },
};

View File

@@ -11230,7 +11230,8 @@ static int netif_alloc_netdev_queues(struct net_device *dev)
netdev_for_each_tx_queue(dev, netdev_init_one_queue, NULL);
spin_lock_init(&dev->tx_global_lock);
spin_lock_init(&dev->watchdog_lock);
dev->watchdog_ref_held = false;
return 0;
}

View File

@@ -349,7 +349,7 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,
if (err != -EAGAIN) {
if ((arg->flags & FIB_LOOKUP_NOREF) ||
likely(refcount_inc_not_zero(&rule->refcnt))) {
likely(fib_rule_get_safe(rule))) {
arg->rule = rule;
goto out;
}
@@ -410,8 +410,12 @@ int fib_rules_dump(struct net *net, struct notifier_block *nb, int family,
if (!ops)
return -EAFNOSUPPORT;
list_for_each_entry_rcu(rule, &ops->rules_list, list) {
if (!fib_rule_get_safe(rule))
continue;
err = call_fib_rule_notifier(nb, FIB_EVENT_RULE_ADD,
rule, family, extack);
fib_rule_put(rule);
if (err)
break;
}

View File

@@ -2733,11 +2733,13 @@ BPF_CALL_4(bpf_msg_pull_data, struct sk_msg *, msg, u32, start,
poffset += len;
sge->length = 0;
put_page(sg_page(sge));
__clear_bit(i, msg->sg.copy);
sk_msg_iter_var_next(i);
} while (i != last_sge);
sg_set_page(&msg->sg.data[first_sge], page, copy, 0);
__clear_bit(first_sge, msg->sg.copy);
/* To repair sg ring we need to shift entries. If we only
* had a single entry though we can just replace it and
@@ -2763,9 +2765,11 @@ BPF_CALL_4(bpf_msg_pull_data, struct sk_msg *, msg, u32, start,
break;
msg->sg.data[i] = msg->sg.data[move_from];
sk_msg_sg_copy_assign(msg, i, msg, move_from);
msg->sg.data[move_from].length = 0;
msg->sg.data[move_from].page_link = 0;
msg->sg.data[move_from].offset = 0;
__clear_bit(move_from, msg->sg.copy);
sk_msg_iter_var_next(i);
} while (1);
@@ -2794,6 +2798,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
{
struct scatterlist sge, nsge, nnsge, rsge = {0}, *psge;
u32 new, i = 0, l = 0, space, copy = 0, offset = 0;
bool sge_copy, nsge_copy, nnsge_copy, rsge_copy = false;
u8 *raw, *to, *from;
struct page *page;
@@ -2866,6 +2871,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
sk_msg_iter_var_prev(i);
psge = sk_msg_elem(msg, i);
rsge = sk_msg_elem_cpy(msg, i);
rsge_copy = test_bit(i, msg->sg.copy);
psge->length = start - offset;
rsge.length -= psge->length;
@@ -2890,24 +2896,32 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
/* Shift one or two slots as needed */
sge = sk_msg_elem_cpy(msg, new);
sge_copy = test_bit(new, msg->sg.copy);
sg_unmark_end(&sge);
nsge = sk_msg_elem_cpy(msg, i);
nsge_copy = test_bit(i, msg->sg.copy);
if (rsge.length) {
sk_msg_iter_var_next(i);
nnsge = sk_msg_elem_cpy(msg, i);
nnsge_copy = test_bit(i, msg->sg.copy);
sk_msg_iter_next(msg, end);
}
while (i != msg->sg.end) {
msg->sg.data[i] = sge;
__assign_bit(i, msg->sg.copy, sge_copy);
sge = nsge;
sge_copy = nsge_copy;
sk_msg_iter_var_next(i);
if (rsge.length) {
nsge = nnsge;
nsge_copy = nnsge_copy;
nnsge = sk_msg_elem_cpy(msg, i);
nnsge_copy = test_bit(i, msg->sg.copy);
} else {
nsge = sk_msg_elem_cpy(msg, i);
nsge_copy = test_bit(i, msg->sg.copy);
}
}
@@ -2921,6 +2935,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
get_page(sg_page(&rsge));
sk_msg_iter_var_next(new);
msg->sg.data[new] = rsge;
__assign_bit(new, msg->sg.copy, rsge_copy);
}
sk_msg_reset_curr(msg);
@@ -2948,25 +2963,33 @@ static void sk_msg_shift_left(struct sk_msg *msg, int i)
prev = i;
sk_msg_iter_var_next(i);
msg->sg.data[prev] = msg->sg.data[i];
sk_msg_sg_copy_assign(msg, prev, msg, i);
} while (i != msg->sg.end);
sk_msg_iter_prev(msg, end);
__clear_bit(msg->sg.end, msg->sg.copy);
}
static void sk_msg_shift_right(struct sk_msg *msg, int i)
{
struct scatterlist tmp, sge;
bool tmp_copy, sge_copy;
sk_msg_iter_next(msg, end);
sge = sk_msg_elem_cpy(msg, i);
sge_copy = test_bit(i, msg->sg.copy);
sk_msg_iter_var_next(i);
tmp = sk_msg_elem_cpy(msg, i);
tmp_copy = test_bit(i, msg->sg.copy);
while (i != msg->sg.end) {
msg->sg.data[i] = sge;
__assign_bit(i, msg->sg.copy, sge_copy);
sk_msg_iter_var_next(i);
sge = tmp;
sge_copy = tmp_copy;
tmp = sk_msg_elem_cpy(msg, i);
tmp_copy = test_bit(i, msg->sg.copy);
}
}
@@ -3026,6 +3049,8 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
struct scatterlist *nsge, *sge = sk_msg_elem(msg, i);
int a = start - offset;
int b = sge->length - pop - a;
u32 sge_i = i;
bool sge_copy = test_bit(i, msg->sg.copy);
sk_msg_iter_var_next(i);
@@ -3038,6 +3063,7 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
sg_set_page(nsge,
sg_page(sge),
b, sge->offset + pop + a);
__assign_bit(i, msg->sg.copy, sge_copy);
} else {
struct page *page, *orig;
u8 *to, *from;
@@ -3054,6 +3080,7 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
memcpy(to, from, a);
memcpy(to + a, from + a + pop, b);
sg_set_page(sge, page, a + b, 0);
__clear_bit(sge_i, msg->sg.copy);
put_page(orig);
}
pop = 0;

View File

@@ -338,12 +338,12 @@ void __netif_mp_uninstall_rxq(struct netdev_rx_queue *rxq,
void netif_rxq_cleanup_unlease(struct netdev_rx_queue *phys_rxq,
struct netdev_rx_queue *virt_rxq)
{
struct pp_memory_provider_params *p = &phys_rxq->mp_params;
unsigned int rxq_idx = get_netdev_rx_queue_index(phys_rxq);
struct pp_memory_provider_params p = phys_rxq->mp_params;
if (!p->mp_ops)
if (!p.mp_ops)
return;
__netif_mp_uninstall_rxq(virt_rxq, p);
__netif_mp_close_rxq(phys_rxq->dev, rxq_idx, p);
__netif_mp_close_rxq(phys_rxq->dev, rxq_idx, &p);
__netif_mp_uninstall_rxq(virt_rxq, &p);
}

View File

@@ -65,6 +65,7 @@ int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len,
sge = &msg->sg.data[msg->sg.end];
sg_unmark_end(sge);
sg_set_page(sge, pfrag->page, use, orig_offset);
__clear_bit(msg->sg.end, msg->sg.copy);
get_page(pfrag->page);
sk_msg_iter_next(msg, end);
}
@@ -185,6 +186,7 @@ static int sk_msg_free_elem(struct sock *sk, struct sk_msg *msg, u32 i,
sk_mem_uncharge(sk, len);
put_page(sg_page(sge));
}
__clear_bit(i, msg->sg.copy);
memset(sge, 0, sizeof(*sge));
return len;
}

View File

@@ -79,7 +79,7 @@ void *ife_decode(struct sk_buff *skb, u16 *metalen)
if (unlikely(ifehdrln < 2))
return NULL;
if (unlikely(!pskb_may_pull(skb, total_pull)))
if (unlikely(!pskb_may_pull(skb, total_pull + ETH_HLEN)))
return NULL;
ifehdr = (struct ifeheadr *)(skb->data + skb->dev->hard_header_len);

View File

@@ -2166,10 +2166,14 @@ static int fib_leaf_notify(struct key_vector *l, struct fib_table *tb,
if (fa->fa_slen == last_slen)
continue;
if (!fib_info_hold_safe(fa->fa_info))
continue;
last_slen = fa->fa_slen;
err = call_fib_entry_notifier(nb, FIB_EVENT_ENTRY_REPLACE,
l->key, KEYLENGTH - fa->fa_slen,
fa, extack);
fib_info_put(fa->fa_info);
if (err)
return err;
}

View File

@@ -1281,6 +1281,7 @@ void inet_csk_destroy_sock(struct sock *sk)
void inet_csk_prepare_for_destroy_sock(struct sock *sk)
{
/* The below has to be done to allow calling inet_csk_destroy_sock */
tcp_clear_sock_ops_cb_flags(sk);
sock_set_flag(sk, SOCK_DEAD);
tcp_orphan_count_inc();
}

View File

@@ -3277,11 +3277,11 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)
/*
* Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and
* corresponding MSS is IPV6_MAXPLEN - tcp_header_size.
* IPV6_MAXPLEN is also valid and means: "any MSS,
* rely only on pmtu discovery"
* Limit the default MSS to GSO_BY_FRAGS - 1 to avoid
* collision with the GSO_BY_FRAGS magic value (0xFFFF).
*/
if (mtu > IPV6_MAXPLEN - sizeof(struct tcphdr))
mtu = IPV6_MAXPLEN;
mtu = min_t(unsigned int, IPV6_MAXPLEN, GSO_BY_FRAGS - 1);
return mtu;
}

View File

@@ -1302,8 +1302,8 @@ static int kcm_attach(struct socket *sock, struct socket *csock,
psock->save_write_space = csk->sk_write_space;
psock->save_state_change = csk->sk_state_change;
csk->sk_user_data = psock;
csk->sk_data_ready = psock_data_ready;
csk->sk_write_space = psock_write_space;
WRITE_ONCE(csk->sk_data_ready, psock_data_ready);
WRITE_ONCE(csk->sk_write_space, psock_write_space);
csk->sk_state_change = psock_state_change;
write_unlock_bh(&csk->sk_callback_lock);
@@ -1379,8 +1379,8 @@ static void kcm_unattach(struct kcm_psock *psock)
*/
write_lock_bh(&csk->sk_callback_lock);
csk->sk_user_data = NULL;
csk->sk_data_ready = psock->save_data_ready;
csk->sk_write_space = psock->save_write_space;
WRITE_ONCE(csk->sk_data_ready, psock->save_data_ready);
WRITE_ONCE(csk->sk_write_space, psock->save_write_space);
csk->sk_state_change = psock->save_state_change;
strp_stop(&psock->strp);

View File

@@ -496,7 +496,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
if (cb->dst_port == QRTR_PORT_CTRL_LEGACY)
cb->dst_port = QRTR_PORT_CTRL;
if (!size || len != ALIGN(size, 4) + hdrlen)
if (!size || size > len || len != ALIGN(size, 4) + hdrlen)
goto err;
if ((cb->type == QRTR_TYPE_NEW_SERVER ||

View File

@@ -471,13 +471,26 @@ int rxrpc_kernel_charge_accept(struct socket *sock, rxrpc_notify_rx_t notify_rx,
unsigned long user_call_ID, gfp_t gfp,
unsigned int debug_id)
{
struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
struct rxrpc_backlog *b = rx->backlog;
struct rxrpc_backlog *b;
struct rxrpc_sock *rx;
struct sock *sk;
int ret;
if (sock->sk->sk_state == RXRPC_CLOSE)
return -ESHUTDOWN;
sk = sock->sk;
rx = rxrpc_sk(sk);
return rxrpc_service_prealloc_one(rx, b, notify_rx, user_call_ID,
gfp, debug_id);
lock_sock(sk);
if (sk->sk_state != RXRPC_SERVER_LISTENING || !rx->backlog) {
ret = -ESHUTDOWN;
goto out;
}
b = rx->backlog;
ret = rxrpc_service_prealloc_one(rx, b, notify_rx, user_call_ID,
gfp, debug_id);
out:
release_sock(sk);
return ret;
}
EXPORT_SYMBOL(rxrpc_kernel_charge_accept);

View File

@@ -161,7 +161,7 @@ static int rxrpc_verify_data(struct rxrpc_call *call, struct sk_buff *skb)
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
int ret;
if (sp->len > call->rx_dec_bsize) {
if (sp->len > call->rx_dec_bsize || !call->rx_dec_buffer) {
/* Make sure we can hold a 1412-byte jumbo subpacket and make
* sure that the buffer size is aligned to a crypto blocksize.
*/
@@ -262,12 +262,13 @@ static int rxrpc_recvmsg_oob(struct socket *sock, struct msghdr *msg,
break;
}
if (!(flags & MSG_PEEK))
if (!(flags & MSG_PEEK)) {
skb_unlink(skb, &rx->recvmsg_oobq);
if (need_response)
rxrpc_add_pending_oob(rx, skb);
else
rxrpc_free_skb(skb, rxrpc_skb_put_oob);
if (need_response)
rxrpc_add_pending_oob(rx, skb);
else
rxrpc_free_skb(skb, rxrpc_skb_put_oob);
}
return ret;
}

View File

@@ -687,16 +687,17 @@ static int rxgk_issue_challenge(struct rxrpc_connection *conn)
ret = do_udp_sendmsg(conn->local->socket, &msg, len);
if (ret > 0)
rxrpc_peer_mark_tx(conn->peer);
__free_page(page);
if (ret < 0) {
trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
rxrpc_tx_point_rxgk_challenge);
__free_page(page);
return -EAGAIN;
}
trace_rxrpc_tx_packet(conn->debug_id, whdr,
rxrpc_tx_point_rxgk_challenge);
__free_page(page);
_leave(" = 0");
return 0;
}

View File

@@ -21,6 +21,7 @@
#include <net/inet_sock.h>
#include <net/pkt_cls.h>
#include <linux/siphash.h>
#include <net/ip.h>
#include <net/route.h>
#include <net/flow_dissector.h>
@@ -57,11 +58,15 @@ struct flow_filter {
struct rcu_work rwork;
};
static siphash_aligned_key_t flow_keys_secret __read_mostly;
static inline u32 addr_fold(void *addr)
{
unsigned long a = (unsigned long)addr;
return (a & 0xFFFFFFFF) ^ (BITS_PER_LONG > 32 ? a >> 32 : 0);
#ifdef CONFIG_64BIT
return (u32)siphash_1u64((u64)addr, &flow_keys_secret);
#else
return (u32)siphash_1u32((u32)addr, &flow_keys_secret);
#endif
}
static u32 flow_get_src(const struct sk_buff *skb, const struct flow_keys *flow)
@@ -596,6 +601,7 @@ static int flow_init(struct tcf_proto *tp)
return -ENOBUFS;
INIT_LIST_HEAD(&head->filters);
rcu_assign_pointer(tp->root, head);
net_get_random_once(&flow_keys_secret, sizeof(flow_keys_secret));
return 0;
}

View File

@@ -56,7 +56,7 @@ static void drop_func(struct sk_buff *skb, void *ctx)
qdisc_qstats_drop(sch);
}
static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch)
static struct sk_buff *__codel_qdisc_dequeue(struct Qdisc *sch)
{
struct codel_sched_data *q = qdisc_priv(sch);
struct sk_buff *skb;
@@ -65,13 +65,51 @@ static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch)
&q->stats, qdisc_pkt_len, codel_get_enqueue_time,
drop_func, dequeue_func);
if (skb)
qdisc_bstats_update(sch, skb);
return skb;
}
static void codel_dequeue_drop(struct Qdisc *sch)
{
struct codel_sched_data *q = qdisc_priv(sch);
if (q->stats.drop_count) {
qdisc_tree_reduce_backlog(sch, q->stats.drop_count, q->stats.drop_len);
qdisc_tree_reduce_backlog(sch, q->stats.drop_count,
q->stats.drop_len);
q->stats.drop_count = 0;
q->stats.drop_len = 0;
}
if (skb)
qdisc_bstats_update(sch, skb);
}
static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch)
{
struct sk_buff *skb;
skb = __codel_qdisc_dequeue(sch);
codel_dequeue_drop(sch);
return skb;
}
static struct sk_buff *codel_peek(struct Qdisc *sch)
{
struct sk_buff *skb = skb_peek(&sch->gso_skb);
if (!skb) {
skb = __codel_qdisc_dequeue(sch);
if (skb) {
__skb_queue_head(&sch->gso_skb, skb);
/* it's still part of the queue */
qdisc_qstats_backlog_inc(sch, skb);
sch->q.qlen++;
}
codel_dequeue_drop(sch);
}
return skb;
}
@@ -257,7 +295,7 @@ static struct Qdisc_ops codel_qdisc_ops __read_mostly = {
.enqueue = codel_qdisc_enqueue,
.dequeue = codel_qdisc_dequeue,
.peek = qdisc_peek_dequeued,
.peek = codel_peek,
.init = codel_init,
.reset = codel_reset,
.change = codel_change,

View File

@@ -578,7 +578,7 @@ static void drop_and_retry(struct dualpi2_sched_data *q, struct sk_buff *skb,
qdisc_qstats_drop(sch);
}
static struct sk_buff *dualpi2_qdisc_dequeue(struct Qdisc *sch)
static struct sk_buff *__dualpi2_qdisc_dequeue(struct Qdisc *sch)
{
struct dualpi2_sched_data *q = qdisc_priv(sch);
struct sk_buff *skb;
@@ -605,12 +605,49 @@ static struct sk_buff *dualpi2_qdisc_dequeue(struct Qdisc *sch)
break;
}
return skb;
}
static void dualpi2_dequeue_drop(struct Qdisc *sch)
{
struct dualpi2_sched_data *q = qdisc_priv(sch);
if (q->deferred_drops_cnt) {
qdisc_tree_reduce_backlog(sch, q->deferred_drops_cnt,
q->deferred_drops_len);
q->deferred_drops_cnt = 0;
q->deferred_drops_len = 0;
}
}
static struct sk_buff *dualpi2_qdisc_dequeue(struct Qdisc *sch)
{
struct sk_buff *skb;
skb = __dualpi2_qdisc_dequeue(sch);
dualpi2_dequeue_drop(sch);
return skb;
}
static struct sk_buff *dualpi2_peek(struct Qdisc *sch)
{
struct sk_buff *skb = skb_peek(&sch->gso_skb);
if (!skb) {
skb = __dualpi2_qdisc_dequeue(sch);
if (skb) {
__skb_queue_head(&sch->gso_skb, skb);
/* it's still part of the queue */
qdisc_qstats_backlog_inc(sch, skb);
sch->q.qlen++;
}
dualpi2_dequeue_drop(sch);
}
return skb;
}
@@ -1165,7 +1202,7 @@ static struct Qdisc_ops dualpi2_qdisc_ops __read_mostly = {
.priv_size = sizeof(struct dualpi2_sched_data),
.enqueue = dualpi2_qdisc_enqueue,
.dequeue = dualpi2_qdisc_dequeue,
.peek = qdisc_peek_dequeued,
.peek = dualpi2_peek,
.init = dualpi2_init,
.destroy = dualpi2_destroy,
.reset = dualpi2_reset,
@@ -1174,6 +1211,7 @@ static struct Qdisc_ops dualpi2_qdisc_ops __read_mostly = {
.dump_stats = dualpi2_dump_stats,
.owner = THIS_MODULE,
};
MODULE_ALIAS_NET_SCH("dualpi2");
static int __init dualpi2_module_init(void)
{

View File

@@ -281,7 +281,7 @@ static void drop_func(struct sk_buff *skb, void *ctx)
qdisc_qstats_drop(sch);
}
static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch)
static struct sk_buff *__fq_codel_dequeue(struct Qdisc *sch)
{
struct fq_codel_sched_data *q = qdisc_priv(sch);
struct sk_buff *skb;
@@ -318,12 +318,49 @@ static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch)
qdisc_bstats_update(sch, skb);
WRITE_ONCE(flow->deficit, flow->deficit - qdisc_pkt_len(skb));
return skb;
}
static void fq_codel_dequeue_drop(struct Qdisc *sch)
{
struct fq_codel_sched_data *q = qdisc_priv(sch);
if (q->cstats.drop_count) {
qdisc_tree_reduce_backlog(sch, q->cstats.drop_count,
q->cstats.drop_len);
q->cstats.drop_count = 0;
q->cstats.drop_len = 0;
}
}
static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch)
{
struct sk_buff *skb;
skb = __fq_codel_dequeue(sch);
fq_codel_dequeue_drop(sch);
return skb;
}
static struct sk_buff *fq_codel_peek(struct Qdisc *sch)
{
struct sk_buff *skb = skb_peek(&sch->gso_skb);
if (!skb) {
skb = __fq_codel_dequeue(sch);
if (skb) {
__skb_queue_head(&sch->gso_skb, skb);
/* it's still part of the queue */
qdisc_qstats_backlog_inc(sch, skb);
sch->q.qlen++;
}
fq_codel_dequeue_drop(sch);
}
return skb;
}
@@ -726,7 +763,7 @@ static struct Qdisc_ops fq_codel_qdisc_ops __read_mostly = {
.priv_size = sizeof(struct fq_codel_sched_data),
.enqueue = fq_codel_enqueue,
.dequeue = fq_codel_dequeue,
.peek = qdisc_peek_dequeued,
.peek = fq_codel_peek,
.init = fq_codel_init,
.reset = fq_codel_reset,
.destroy = fq_codel_destroy,

View File

@@ -568,16 +568,24 @@ static void dev_watchdog(struct timer_list *t)
dev->netdev_ops->ndo_tx_timeout(dev, i);
netif_unfreeze_queues(dev);
}
if (!mod_timer(&dev->watchdog_timer,
round_jiffies(oldest_start +
dev->watchdog_timeo)))
release = false;
spin_lock(&dev->watchdog_lock);
mod_timer(&dev->watchdog_timer,
round_jiffies(oldest_start +
dev->watchdog_timeo));
release = false;
spin_unlock(&dev->watchdog_lock);
}
}
spin_unlock(&dev->tx_global_lock);
if (release)
spin_lock(&dev->watchdog_lock);
if (timer_pending(&dev->watchdog_timer))
release = false;
if (release && dev->watchdog_ref_held) {
netdev_put(dev, &dev->watchdog_dev_tracker);
dev->watchdog_ref_held = false;
}
spin_unlock(&dev->watchdog_lock);
}
void netdev_watchdog_up(struct net_device *dev)
@@ -586,18 +594,34 @@ void netdev_watchdog_up(struct net_device *dev)
return;
if (dev->watchdog_timeo <= 0)
dev->watchdog_timeo = 5*HZ;
spin_lock_bh(&dev->tx_global_lock);
spin_lock(&dev->watchdog_lock);
if (!mod_timer(&dev->watchdog_timer,
round_jiffies(jiffies + dev->watchdog_timeo)))
netdev_hold(dev, &dev->watchdog_dev_tracker,
GFP_ATOMIC);
round_jiffies(jiffies + dev->watchdog_timeo))) {
if (!dev->watchdog_ref_held) {
netdev_hold(dev, &dev->watchdog_dev_tracker,
GFP_ATOMIC);
dev->watchdog_ref_held = true;
}
}
spin_unlock(&dev->watchdog_lock);
spin_unlock_bh(&dev->tx_global_lock);
}
EXPORT_SYMBOL_GPL(netdev_watchdog_up);
static void netdev_watchdog_down(struct net_device *dev)
{
netif_tx_lock_bh(dev);
if (timer_delete(&dev->watchdog_timer))
spin_lock(&dev->watchdog_lock);
if (timer_delete(&dev->watchdog_timer)) {
netdev_put(dev, &dev->watchdog_dev_tracker);
dev->watchdog_ref_held = false;
}
spin_unlock(&dev->watchdog_lock);
netif_tx_unlock_bh(dev);
}
@@ -617,8 +641,6 @@ void netif_carrier_on(struct net_device *dev)
return;
atomic_inc(&dev->carrier_up_count);
linkwatch_fire_event(dev);
if (netif_running(dev))
netdev_watchdog_up(dev);
}
}
EXPORT_SYMBOL(netif_carrier_on);

View File

@@ -753,7 +753,7 @@ update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time)
u64 f; /* , myf_bound, delta; */
int go_passive = 0;
if (cl->qdisc->q.qlen == 0 && cl->cl_flags & HFSC_FSC)
if (cl->qdisc->q.qlen == 0 && cl->cl_flags & HFSC_FSC && cl->cl_nactive)
go_passive = 1;
for (; cl->cl_parent != NULL; cl = cl->cl_parent) {

View File

@@ -2641,6 +2641,9 @@ static int sctp_process_param(struct sctp_association *asoc,
goto fall_through;
addr_param = param.v + sizeof(struct sctp_addip_param);
if (ntohs(addr_param->p.length) >
ntohs(param.p->length) - sizeof(struct sctp_addip_param))
break;
af = sctp_get_af_specific(param_type2af(addr_param->p.type));
if (!af)
@@ -3039,13 +3042,16 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
union sctp_addr addr;
struct sctp_af *af;
addr_param = (void *)asconf_param + sizeof(*asconf_param);
if (asconf_param->param_hdr.type != SCTP_PARAM_ADD_IP &&
asconf_param->param_hdr.type != SCTP_PARAM_DEL_IP &&
asconf_param->param_hdr.type != SCTP_PARAM_SET_PRIMARY)
return SCTP_ERROR_UNKNOWN_PARAM;
addr_param = (void *)asconf_param + sizeof(*asconf_param);
if (ntohs(addr_param->p.length) >
ntohs(asconf_param->param_hdr.length) - sizeof(*asconf_param))
return SCTP_ERROR_PROTO_VIOLATION;
switch (addr_param->p.type) {
case SCTP_PARAM_IPV6_ADDRESS:
if (!asoc->peer.ipv6_address)

View File

@@ -482,6 +482,7 @@ void tipc_disable_l2_media(struct tipc_bearer *b)
dev = (struct net_device *)rtnl_dereference(b->media_ptr);
dev_remove_pack(&b->pt);
RCU_INIT_POINTER(dev->tipc_ptr, NULL);
RCU_INIT_POINTER(b->media_ptr, NULL);
synchronize_net();
dev_put(dev);
}

View File

@@ -280,12 +280,21 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i,
u32 node, u32 dtype)
{
struct publication *p = NULL;
u32 lower = ntohl(i->lower);
u32 upper = ntohl(i->upper);
struct tipc_socket_addr sk;
struct tipc_uaddr ua;
u32 key = ntohl(i->key);
struct tipc_uaddr ua;
/* A peer-advertised binding with lower > upper can never be matched
* or withdrawn and would leak the publication; the local bind path
* rejects such ranges, so reject ranges learned from the network too.
*/
if (lower > upper)
return false;
tipc_uaddr(&ua, TIPC_SERVICE_RANGE, TIPC_CLUSTER_SCOPE,
ntohl(i->type), ntohl(i->lower), ntohl(i->upper));
ntohl(i->type), lower, upper);
sk.ref = ntohl(i->port);
sk.node = node;

View File

@@ -152,11 +152,13 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
{
.cmd = TIPC_NL_BEARER_DISABLE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = tipc_nl_bearer_disable,
},
{
.cmd = TIPC_NL_BEARER_ENABLE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = tipc_nl_bearer_enable,
},
{
@@ -168,11 +170,13 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
{
.cmd = TIPC_NL_BEARER_ADD,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = tipc_nl_bearer_add,
},
{
.cmd = TIPC_NL_BEARER_SET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = tipc_nl_bearer_set,
},
{
@@ -197,11 +201,13 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
{
.cmd = TIPC_NL_LINK_SET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = tipc_nl_node_set_link,
},
{
.cmd = TIPC_NL_LINK_RESET_STATS,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = tipc_nl_node_reset_link_stats,
},
{
@@ -213,6 +219,7 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
{
.cmd = TIPC_NL_MEDIA_SET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = tipc_nl_media_set,
},
{
@@ -228,6 +235,7 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
{
.cmd = TIPC_NL_NET_SET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = tipc_nl_net_set,
},
{
@@ -238,6 +246,7 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
{
.cmd = TIPC_NL_MON_SET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = tipc_nl_node_set_monitor,
},
{
@@ -255,6 +264,7 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
{
.cmd = TIPC_NL_PEER_REMOVE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = tipc_nl_peer_rm,
},
#ifdef CONFIG_TIPC_MEDIA_UDP
@@ -269,11 +279,13 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
{
.cmd = TIPC_NL_KEY_SET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = tipc_nl_node_set_key,
},
{
.cmd = TIPC_NL_KEY_FLUSH,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = tipc_nl_node_flush_key,
},
#endif

View File

@@ -1363,6 +1363,9 @@ static void tipc_sk_conn_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,
__skb_queue_tail(xmitq, skb);
return;
} else if (mtyp == CONN_ACK) {
if (tsk->snt_unacked < msg_conn_ack(hdr))
goto exit;
was_cong = tsk_conn_cong(tsk);
tipc_sk_push_backlog(tsk, msg_nagle_ack(hdr));
tsk->snt_unacked -= msg_conn_ack(hdr);
@@ -2453,17 +2456,17 @@ static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk,
atomic_set(dcnt, 0);
lim = rcvbuf_limit(sk, skb) + atomic_read(dcnt);
if (likely(!sk_add_backlog(sk, skb, lim))) {
trace_tipc_sk_overlimit1(sk, skb, TIPC_DUMP_ALL,
trace_tipc_sk_overlimit1(sk, skb, TIPC_DUMP_SK_BKLGQ,
"bklg & rcvq >90% allocated!");
continue;
}
trace_tipc_sk_dump(sk, skb, TIPC_DUMP_ALL, "err_overload!");
trace_tipc_sk_dump(sk, skb, TIPC_DUMP_SK_BKLGQ, "err_overload!");
/* Overload => reject message back to sender */
onode = tipc_own_addr(sock_net(sk));
sk_drops_inc(sk);
if (tipc_msg_reverse(onode, &skb, TIPC_ERR_OVERLOAD)) {
trace_tipc_sk_rej_msg(sk, skb, TIPC_DUMP_ALL,
trace_tipc_sk_rej_msg(sk, skb, TIPC_DUMP_SK_BKLGQ,
"@sk_enqueue!");
__skb_queue_tail(xmitq, skb);
}

View File

@@ -1378,5 +1378,60 @@
"teardown": [
"$TC actions flush action ife"
]
},
{
"id": "4e6b",
"name": "Decode IFE packet with truncated inner Ethernet header",
"category": [
"actions",
"ife"
],
"plugins": {
"requires": [
"nsPlugin",
"scapyPlugin"
]
},
"setup": [
[
"$TC actions flush action ife",
0,
1,
255
],
"$TC qdisc add dev $DEV1 clsact"
],
"scapy": [
{
"iface": "$DEV0",
"count": 1,
"packet": "Ether(type=0xED3E) / Raw(b'\\x00\\x02\\xaa')"
}
],
"cmdUnderTest": "$TC filter add dev $DEV1 ingress protocol all matchall action ife decode pipe index 10",
"expExitCode": "0",
"verifyCmd": "$TC -s -j actions get action ife index 10",
"matchJSON": [
{
"total acts": 0
},
{
"actions": [
{
"kind": "ife",
"mode": "decode",
"index": 10,
"stats": {
"bytes": 3,
"packets": 1,
"drops": 1
}
}
]
}
],
"teardown": [
"$TC qdisc del dev $DEV1 clsact"
]
}
]

View File

@@ -1356,5 +1356,189 @@
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
},
{
"id": "c797",
"name": "Verify fq_codel won't mistakenly deactivate QFQ parent class during peek",
"category": [
"qdisc",
"qfq",
"fq_codel"
],
"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 root handle 1: qfq",
"$TC class add dev $DUMMY parent 1: classid 1:1 qfq weight 1 maxpkt 1000",
"$TC class add dev $DUMMY parent 1: classid 1:2 qfq weight 1 maxpkt 1000",
"$TC qdisc add dev $DUMMY parent 1:1 handle 2:0 plug limit 1024",
"$IP l set dev $DUMMY mtu 1500",
"$TC qdisc add dev $DUMMY parent 1:2 handle 10: fq_codel target 1 interval 1 flows 1",
"$TC filter add dev $DUMMY parent 1: protocol ip prio 1 u32 match ip dst 10.10.10.1/32 flowid 1:1",
"$TC filter add dev $DUMMY parent 1: protocol ip prio 2 u32 match ip dst 10.10.10.2/32 flowid 1:2",
"$IP l set dev $DUMMY mtu 65336",
"ping -c 1 -I $DUMMY 10.10.10.1 -W0.01 > /dev/null || true",
"ping -c 3 -s 2000 -I $DUMMY 10.10.10.2 -W0.01 > /dev/null || true",
"sleep 0.1"
],
"cmdUnderTest": "$TC qdisc change dev $DUMMY handle 2:0 plug release_indefinite",
"expExitCode": "0",
"verifyCmd": "$TC -s -j qdisc show dev $DUMMY",
"matchJSON": [
{
"kind": "qfq",
"handle": "1:",
"packets": 3,
"drops": 1,
"backlog": 0,
"qlen": 0
},
{
"kind": "plug",
"handle": "2:",
"packets": 1,
"drops": 0,
"backlog": 0,
"qlen": 0
},
{
"kind": "fq_codel",
"handle": "10:",
"packets": 2,
"drops": 1,
"backlog": 0,
"qlen": 0
}
],
"teardown": [
"$TC qdisc del dev $DUMMY root",
"$IP addr del 10.10.10.10/24 dev $DUMMY || true"
]
},
{
"id": "82d9",
"name": "Verify codel won't mistakenly deactivate QFQ parent class during peek",
"category": [
"qdisc",
"qfq",
"codel"
],
"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 root handle 1: qfq",
"$TC class add dev $DUMMY parent 1: classid 1:1 qfq weight 1 maxpkt 1000",
"$TC class add dev $DUMMY parent 1: classid 1:2 qfq weight 1 maxpkt 1000",
"$TC qdisc add dev $DUMMY parent 1:1 handle 2:0 plug limit 1024",
"$IP l set dev $DUMMY mtu 1500",
"$TC qdisc add dev $DUMMY parent 1:2 handle 10: codel target 1ms interval 1ms",
"$TC filter add dev $DUMMY parent 1: protocol ip prio 1 u32 match ip dst 10.10.10.1/32 flowid 1:1",
"$TC filter add dev $DUMMY parent 1: protocol ip prio 2 u32 match ip dst 10.10.10.2/32 flowid 1:2",
"$IP l set dev $DUMMY mtu 65336",
"ping -c 1 -I $DUMMY 10.10.10.1 -W0.01 > /dev/null || true",
"ping -c 3 -s 2000 -I $DUMMY 10.10.10.2 -W0.01 > /dev/null || true",
"sleep 0.1"
],
"cmdUnderTest": "$TC qdisc change dev $DUMMY handle 2:0 plug release_indefinite",
"expExitCode": "0",
"verifyCmd": "$TC -s -j qdisc show dev $DUMMY",
"matchJSON": [
{
"kind": "qfq",
"handle": "1:",
"packets": 3,
"drops": 1,
"backlog": 0,
"qlen": 0
},
{
"kind": "plug",
"handle": "2:",
"packets": 1,
"drops": 0,
"backlog": 0,
"qlen": 0
},
{
"kind": "codel",
"handle": "10:",
"packets": 2,
"drops": 1,
"backlog": 0,
"qlen": 0
}
],
"teardown": [
"$TC qdisc del dev $DUMMY root",
"$IP addr del 10.10.10.10/24 dev $DUMMY || true"
]
},
{
"id": "d3da",
"name": "Verify dualpi2 won't mistakenly deactivate QFQ parent class during peek",
"category": [
"qdisc",
"qfq",
"dualpi2"
],
"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 root handle 1: qfq",
"$TC class add dev $DUMMY parent 1: classid 1:1 qfq weight 1 maxpkt 1000",
"$TC class add dev $DUMMY parent 1: classid 1:2 qfq weight 1 maxpkt 1000",
"$TC qdisc add dev $DUMMY parent 1:1 handle 2:0 plug limit 1024",
"$TC qdisc add dev $DUMMY parent 1:2 handle 10: dualpi2 step_thresh 500ms",
"$TC filter add dev $DUMMY parent 10: protocol ip prio 1 matchall classid 10:1 action ok",
"$TC filter add dev $DUMMY parent 1: protocol ip prio 1 u32 match ip dst 10.10.10.1/32 flowid 1:1",
"$TC filter add dev $DUMMY parent 1: protocol ip prio 2 u32 match ip dst 10.10.10.2/32 flowid 1:2",
"ping -c 1 -I $DUMMY 10.10.10.1 -W0.01 || true",
"ping -c 3 -i 0.1 -I $DUMMY 10.10.10.2 -W0.01 || true",
"sleep 0.7",
"ping -c 1 -I $DUMMY 10.10.10.2 -W0.01 || true",
"$TC qdisc change dev $DUMMY handle 2:0 plug release_indefinite"
],
"cmdUnderTest": "ping -c 1 -I $DUMMY 10.10.10.1 -W0.01",
"expExitCode": "1",
"verifyCmd": "$TC -s -j qdisc show dev $DUMMY",
"matchJSON": [
{
"kind": "qfq",
"handle": "1:",
"packets": 4,
"drops": 2,
"backlog": 0,
"qlen": 0
},
{
"kind": "plug",
"handle": "2:",
"packets": 2,
"drops": 0,
"backlog": 0,
"qlen": 0
},
{
"kind": "dualpi2",
"handle": "10:",
"packets": 2,
"drops": 2,
"backlog": 0,
"qlen": 0
}
],
"teardown": [
"$TC qdisc del dev $DUMMY root",
"$IP addr del 10.10.10.10/24 dev $DUMMY || true"
]
}
]