1
0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2026-01-11 17:10:13 +00:00

Including fixes from netfilter and wireless.

Current release - fix to a fix:
 
  - net: do not write to msg_get_inq in callee
 
  - arp: do not assume dev_hard_header() does not change skb->head
 
 Current release - regressions:
 
  - wifi: mac80211: don't iterate not running interfaces
 
  - eth: mlx5: fix NULL pointer dereference in ioctl module EEPROM
 
 Current release - new code bugs:
 
  - eth: bnge: add AUXILIARY_BUS to Kconfig dependencies
 
 Previous releases - regressions:
 
  - eth: mlx5: dealloc forgotten PSP RX modify header
 
 Previous releases - always broken:
 
  - ping: fix ICMP out SNMP stats double-counting with ICMP sockets
 
  - bonding: preserve NETIF_F_ALL_FOR_ALL across TSO updates
 
  - bridge: fix C-VLAN preservation in 802.1ad vlan_tunnel egress
 
  - eth: bnxt: fix potential data corruption with HW GRO/LRO
 
 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmlf6N8ACgkQMUZtbf5S
 Irt9lxAAote4zPojTEJvE1DkABVsx31gPm6DF8zEae39XsFKtOMfb876s5bchOUA
 Rkd27+k28l/U5HFrrhUhqDlaOikjXx6baT12qTPsuxGrOL6Um23EfIgVuNFzxMwE
 lcBgkSNe1tfT8WBirWEVWLc5xme+vvll7ViX7kkQJ7fEdk1mvTPZ5roIq1+pE1U0
 V5Gu4l9QBcWC/IymAO8Z2UE08terMcYt1G4H6mSIoooeMM1QElbPwVEiRWAzJ/NP
 9cTjvnHJDAdRnA4bMa76CGWxg4wgPhgj3+ydlouWjgJADL6hlMj4sIZxaXgjDuoE
 XyCEuk6Y/rUTSmX1yn7rha9FQwJOyMu9XlEjnNSvH0LRdnSa7xO7NzeXtrWv7HSg
 kQOMTnMVgVlabOuMbR6xNqY6UyulQgK/2E56RgOO4Iw6U7crZsbyZx3OFkIKhq8g
 ZWaRBQNdYBBftjJA7FwQSyj/K75sLfbYAS5YizguNyFPBCBhSBJdgFWoGb+XhT0/
 k0KwsX/NWN0apHmZNiD4mT/UdX2PhJRdiTWPczNyEzqJcxh1P2HMWHVZOsIyZQHT
 EK3w6LLqp1eshEERPqFsqCFYX4LUuifQbPPF0kBkL1hTMa2NuXnkIsOzbcWal88o
 qdej9TY9VC5ycabgDI4/9ZNhnAzho1Nk/e6YuHsBcu2pIVDKgNI=
 =vR9r
 -----END PGP SIGNATURE-----

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

Pull networking fixes from Jakub Kicinski:
 "Including fixes from netfilter and wireless.

  Current release - fix to a fix:

   - net: do not write to msg_get_inq in callee

   - arp: do not assume dev_hard_header() does not change skb->head

  Current release - regressions:

   - wifi: mac80211: don't iterate not running interfaces

   - eth: mlx5: fix NULL pointer dereference in ioctl module EEPROM

  Current release - new code bugs:

   - eth: bnge: add AUXILIARY_BUS to Kconfig dependencies

  Previous releases - regressions:

   - eth: mlx5: dealloc forgotten PSP RX modify header

  Previous releases - always broken:

   - ping: fix ICMP out SNMP stats double-counting with ICMP sockets

   - bonding: preserve NETIF_F_ALL_FOR_ALL across TSO updates

   - bridge: fix C-VLAN preservation in 802.1ad vlan_tunnel egress

   - eth: bnxt: fix potential data corruption with HW GRO/LRO"

* tag 'net-6.19-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (70 commits)
  arp: do not assume dev_hard_header() does not change skb->head
  net: enetc: fix build warning when PAGE_SIZE is greater than 128K
  atm: Fix dma_free_coherent() size
  tools: ynl: don't install tests
  net: do not write to msg_get_inq in callee
  bnxt_en: Fix NULL pointer crash in bnxt_ptp_enable during error cleanup
  net: usb: pegasus: fix memory leak in update_eth_regs_async()
  net: 3com: 3c59x: fix possible null dereference in vortex_probe1()
  net/sched: sch_qfq: Fix NULL deref when deactivating inactive aggregate in qfq_reset
  wifi: mac80211: collect station statistics earlier when disconnect
  wifi: mac80211: restore non-chanctx injection behaviour
  wifi: mac80211_hwsim: disable BHs for hwsim_radio_lock
  wifi: mac80211: don't iterate not running interfaces
  wifi: mac80211_hwsim: fix typo in frequency notification
  wifi: avoid kernel-infoleak from struct iw_point
  net: airoha: Fix schedule while atomic in airoha_ppe_deinit()
  selftests: netdevsim: add carrier state consistency test
  net: netdevsim: fix inconsistent carrier state after link/unlink
  selftests: drv-net: Bring back tool() to driver __init__s
  net/sched: act_api: avoid dereferencing ERR_PTR in tcf_idrinfo_destroy
  ...
This commit is contained in:
Linus Torvalds 2026-01-08 08:40:35 -10:00
commit f2a3b12b30
74 changed files with 638 additions and 373 deletions

View File

@ -416,6 +416,7 @@ Juha Yrjola <at solidboot.com>
Juha Yrjola <juha.yrjola@nokia.com> Juha Yrjola <juha.yrjola@nokia.com>
Juha Yrjola <juha.yrjola@solidboot.com> Juha Yrjola <juha.yrjola@solidboot.com>
Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com> Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com>
Justin Iurman <justin.iurman@gmail.com> <justin.iurman@uliege.be>
Iskren Chernev <me@iskren.info> <iskren.chernev@gmail.com> Iskren Chernev <me@iskren.info> <iskren.chernev@gmail.com>
Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org> Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org>
Kalle Valo <kvalo@kernel.org> <quic_kvalo@quicinc.com> Kalle Valo <kvalo@kernel.org> <quic_kvalo@quicinc.com>

View File

@ -142,7 +142,7 @@ attribute-sets:
name: ifindex name: ifindex
doc: | doc: |
ifindex of the netdev to which the pool belongs. ifindex of the netdev to which the pool belongs.
May be reported as 0 if the page pool was allocated for a netdev May not be reported if the page pool was allocated for a netdev
which got destroyed already (page pools may outlast their netdevs which got destroyed already (page pools may outlast their netdevs
because they wait for all memory to be returned). because they wait for all memory to be returned).
type: u32 type: u32
@ -601,7 +601,9 @@ operations:
name: page-pool-get name: page-pool-get
doc: | doc: |
Get / dump information about Page Pools. Get / dump information about Page Pools.
(Only Page Pools associated with a net_device can be listed.) Only Page Pools associated by the driver with a net_device
can be listed. ifindex will not be reported if the net_device
no longer exists.
attribute-set: page-pool attribute-set: page-pool
do: do:
request: request:

View File

@ -1283,6 +1283,7 @@ F: include/uapi/drm/amdxdna_accel.h
AMD XGBE DRIVER AMD XGBE DRIVER
M: "Shyam Sundar S K" <Shyam-sundar.S-k@amd.com> M: "Shyam Sundar S K" <Shyam-sundar.S-k@amd.com>
M: Raju Rangoju <Raju.Rangoju@amd.com>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
S: Maintained S: Maintained
F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi
@ -18283,7 +18284,7 @@ X: net/wireless/
X: tools/testing/selftests/net/can/ X: tools/testing/selftests/net/can/
NETWORKING [IOAM] NETWORKING [IOAM]
M: Justin Iurman <justin.iurman@uliege.be> M: Justin Iurman <justin.iurman@gmail.com>
S: Maintained S: Maintained
F: Documentation/networking/ioam6* F: Documentation/networking/ioam6*
F: include/linux/ioam6* F: include/linux/ioam6*

View File

@ -1587,7 +1587,8 @@ he_stop(struct he_dev *he_dev)
he_dev->tbrq_base, he_dev->tbrq_phys); he_dev->tbrq_base, he_dev->tbrq_phys);
if (he_dev->tpdrq_base) if (he_dev->tpdrq_base)
dma_free_coherent(&he_dev->pci_dev->dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), dma_free_coherent(&he_dev->pci_dev->dev,
CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq),
he_dev->tpdrq_base, he_dev->tpdrq_phys); he_dev->tpdrq_base, he_dev->tpdrq_phys);
dma_pool_destroy(he_dev->tpd_pool); dma_pool_destroy(he_dev->tpd_pool);

View File

@ -3364,13 +3364,10 @@ static int mv88e6xxx_setup_upstream_port(struct mv88e6xxx_chip *chip, int port)
static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
{ {
struct device_node *phy_handle = NULL;
struct fwnode_handle *ports_fwnode; struct fwnode_handle *ports_fwnode;
struct fwnode_handle *port_fwnode; struct fwnode_handle *port_fwnode;
struct dsa_switch *ds = chip->ds; struct dsa_switch *ds = chip->ds;
struct mv88e6xxx_port *p; struct mv88e6xxx_port *p;
struct dsa_port *dp;
int tx_amp;
int err; int err;
u16 reg; u16 reg;
u32 val; u32 val;
@ -3582,23 +3579,6 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
return err; return err;
} }
if (chip->info->ops->serdes_set_tx_amplitude) {
dp = dsa_to_port(ds, port);
if (dp)
phy_handle = of_parse_phandle(dp->dn, "phy-handle", 0);
if (phy_handle && !of_property_read_u32(phy_handle,
"tx-p2p-microvolt",
&tx_amp))
err = chip->info->ops->serdes_set_tx_amplitude(chip,
port, tx_amp);
if (phy_handle) {
of_node_put(phy_handle);
if (err)
return err;
}
}
/* Port based VLAN map: give each port the same default address /* Port based VLAN map: give each port the same default address
* database, and allow bidirectional communication between the * database, and allow bidirectional communication between the
* CPU and DSA port(s), and the other ports. * CPU and DSA port(s), and the other ports.
@ -4768,7 +4748,6 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
.serdes_irq_mapping = mv88e6352_serdes_irq_mapping, .serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
.serdes_get_regs_len = mv88e6352_serdes_get_regs_len, .serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
.serdes_get_regs = mv88e6352_serdes_get_regs, .serdes_get_regs = mv88e6352_serdes_get_regs,
.serdes_set_tx_amplitude = mv88e6352_serdes_set_tx_amplitude,
.gpio_ops = &mv88e6352_gpio_ops, .gpio_ops = &mv88e6352_gpio_ops,
.phylink_get_caps = mv88e6352_phylink_get_caps, .phylink_get_caps = mv88e6352_phylink_get_caps,
.pcs_ops = &mv88e6352_pcs_ops, .pcs_ops = &mv88e6352_pcs_ops,
@ -5044,7 +5023,6 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.serdes_irq_mapping = mv88e6352_serdes_irq_mapping, .serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
.serdes_get_regs_len = mv88e6352_serdes_get_regs_len, .serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
.serdes_get_regs = mv88e6352_serdes_get_regs, .serdes_get_regs = mv88e6352_serdes_get_regs,
.serdes_set_tx_amplitude = mv88e6352_serdes_set_tx_amplitude,
.gpio_ops = &mv88e6352_gpio_ops, .gpio_ops = &mv88e6352_gpio_ops,
.avb_ops = &mv88e6352_avb_ops, .avb_ops = &mv88e6352_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops, .ptp_ops = &mv88e6352_ptp_ops,
@ -5481,7 +5459,6 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
.serdes_get_stats = mv88e6352_serdes_get_stats, .serdes_get_stats = mv88e6352_serdes_get_stats,
.serdes_get_regs_len = mv88e6352_serdes_get_regs_len, .serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
.serdes_get_regs = mv88e6352_serdes_get_regs, .serdes_get_regs = mv88e6352_serdes_get_regs,
.serdes_set_tx_amplitude = mv88e6352_serdes_set_tx_amplitude,
.phylink_get_caps = mv88e6352_phylink_get_caps, .phylink_get_caps = mv88e6352_phylink_get_caps,
.pcs_ops = &mv88e6352_pcs_ops, .pcs_ops = &mv88e6352_pcs_ops,
}; };

View File

@ -642,10 +642,6 @@ struct mv88e6xxx_ops {
void (*serdes_get_regs)(struct mv88e6xxx_chip *chip, int port, void (*serdes_get_regs)(struct mv88e6xxx_chip *chip, int port,
void *_p); void *_p);
/* SERDES SGMII/Fiber Output Amplitude */
int (*serdes_set_tx_amplitude)(struct mv88e6xxx_chip *chip, int port,
int val);
/* Address Translation Unit operations */ /* Address Translation Unit operations */
int (*atu_get_hash)(struct mv88e6xxx_chip *chip, u8 *hash); int (*atu_get_hash)(struct mv88e6xxx_chip *chip, u8 *hash);
int (*atu_set_hash)(struct mv88e6xxx_chip *chip, u8 hash); int (*atu_set_hash)(struct mv88e6xxx_chip *chip, u8 hash);

View File

@ -25,14 +25,6 @@ static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg,
reg, val); reg, val);
} }
static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg,
u16 val)
{
return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES,
MV88E6352_SERDES_PAGE_FIBER,
reg, val);
}
static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip, static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip,
int lane, int device, int reg, u16 *val) int lane, int device, int reg, u16 *val)
{ {
@ -506,41 +498,3 @@ void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
p[i] = reg; p[i] = reg;
} }
} }
static const int mv88e6352_serdes_p2p_to_reg[] = {
/* Index of value in microvolts corresponds to the register value */
14000, 112000, 210000, 308000, 406000, 504000, 602000, 700000,
};
int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip *chip, int port,
int val)
{
bool found = false;
u16 ctrl, reg;
int err;
int i;
err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
if (err <= 0)
return err;
for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_p2p_to_reg); ++i) {
if (mv88e6352_serdes_p2p_to_reg[i] == val) {
reg = i;
found = true;
break;
}
}
if (!found)
return -EINVAL;
err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_SPEC_CTRL2, &ctrl);
if (err)
return err;
ctrl &= ~MV88E6352_SERDES_OUT_AMP_MASK;
ctrl |= reg;
return mv88e6352_serdes_write(chip, MV88E6352_SERDES_SPEC_CTRL2, ctrl);
}

View File

@ -29,8 +29,6 @@ struct phylink_link_state;
#define MV88E6352_SERDES_INT_FIBRE_ENERGY BIT(4) #define MV88E6352_SERDES_INT_FIBRE_ENERGY BIT(4)
#define MV88E6352_SERDES_INT_STATUS 0x13 #define MV88E6352_SERDES_INT_STATUS 0x13
#define MV88E6352_SERDES_SPEC_CTRL2 0x1a
#define MV88E6352_SERDES_OUT_AMP_MASK 0x0007
#define MV88E6341_PORT5_LANE 0x15 #define MV88E6341_PORT5_LANE 0x15
@ -140,9 +138,6 @@ void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p);
int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port); int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port);
void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p); void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p);
int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip *chip, int port,
int val);
/* Return the (first) SERDES lane address a port is using, -errno otherwise. */ /* Return the (first) SERDES lane address a port is using, -errno otherwise. */
static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip, static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
int port) int port)

View File

@ -1473,7 +1473,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
return 0; return 0;
free_ring: free_ring:
dma_free_coherent(&pdev->dev, dma_free_coherent(gendev,
sizeof(struct boom_rx_desc) * RX_RING_SIZE + sizeof(struct boom_rx_desc) * RX_RING_SIZE +
sizeof(struct boom_tx_desc) * TX_RING_SIZE, sizeof(struct boom_tx_desc) * TX_RING_SIZE,
vp->rx_ring, vp->rx_ring_dma); vp->rx_ring, vp->rx_ring_dma);

View File

@ -1547,13 +1547,16 @@ void airoha_ppe_deinit(struct airoha_eth *eth)
{ {
struct airoha_npu *npu; struct airoha_npu *npu;
rcu_read_lock(); mutex_lock(&flow_offload_mutex);
npu = rcu_dereference(eth->npu);
npu = rcu_replace_pointer(eth->npu, NULL,
lockdep_is_held(&flow_offload_mutex));
if (npu) { if (npu) {
npu->ops.ppe_deinit(npu); npu->ops.ppe_deinit(npu);
airoha_npu_put(npu); airoha_npu_put(npu);
} }
rcu_read_unlock();
mutex_unlock(&flow_offload_mutex);
rhashtable_destroy(&eth->ppe->l2_flows); rhashtable_destroy(&eth->ppe->l2_flows);
rhashtable_destroy(&eth->flow_table); rhashtable_destroy(&eth->flow_table);

View File

@ -53,10 +53,12 @@ void ena_devlink_disable_phc_param(struct devlink *devlink)
{ {
union devlink_param_value value; union devlink_param_value value;
devl_lock(devlink);
value.vbool = false; value.vbool = false;
devl_param_driverinit_value_set(devlink, devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC, DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
value); value);
devl_unlock(devlink);
} }
static void ena_devlink_port_register(struct devlink *devlink) static void ena_devlink_port_register(struct devlink *devlink)
@ -145,10 +147,12 @@ static int ena_devlink_configure_params(struct devlink *devlink)
return rc; return rc;
} }
devl_lock(devlink);
value.vbool = ena_phc_is_enabled(adapter); value.vbool = ena_phc_is_enabled(adapter);
devl_param_driverinit_value_set(devlink, devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC, DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
value); value);
devl_unlock(devlink);
return 0; return 0;
} }

View File

@ -259,6 +259,7 @@ config BNGE
depends on PCI depends on PCI
select NET_DEVLINK select NET_DEVLINK
select PAGE_POOL select PAGE_POOL
select AUXILIARY_BUS
help help
This driver supports Broadcom ThorUltra 50/100/200/400/800 gigabit This driver supports Broadcom ThorUltra 50/100/200/400/800 gigabit
Ethernet cards. The module will be called bng_en. To compile this Ethernet cards. The module will be called bng_en. To compile this

View File

@ -1482,9 +1482,11 @@ static u16 bnxt_alloc_agg_idx(struct bnxt_rx_ring_info *rxr, u16 agg_id)
struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map; struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map;
u16 idx = agg_id & MAX_TPA_P5_MASK; u16 idx = agg_id & MAX_TPA_P5_MASK;
if (test_bit(idx, map->agg_idx_bmap)) if (test_bit(idx, map->agg_idx_bmap)) {
idx = find_first_zero_bit(map->agg_idx_bmap, idx = find_first_zero_bit(map->agg_idx_bmap, MAX_TPA_P5);
BNXT_AGG_IDX_BMAP_SIZE); if (idx >= MAX_TPA_P5)
return INVALID_HW_RING_ID;
}
__set_bit(idx, map->agg_idx_bmap); __set_bit(idx, map->agg_idx_bmap);
map->agg_id_tbl[agg_id] = idx; map->agg_id_tbl[agg_id] = idx;
return idx; return idx;
@ -1548,6 +1550,13 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) { if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
agg_id = TPA_START_AGG_ID_P5(tpa_start); agg_id = TPA_START_AGG_ID_P5(tpa_start);
agg_id = bnxt_alloc_agg_idx(rxr, agg_id); agg_id = bnxt_alloc_agg_idx(rxr, agg_id);
if (unlikely(agg_id == INVALID_HW_RING_ID)) {
netdev_warn(bp->dev, "Unable to allocate agg ID for ring %d, agg 0x%x\n",
rxr->bnapi->index,
TPA_START_AGG_ID_P5(tpa_start));
bnxt_sched_reset_rxr(bp, rxr);
return;
}
} else { } else {
agg_id = TPA_START_AGG_ID(tpa_start); agg_id = TPA_START_AGG_ID(tpa_start);
} }
@ -16882,12 +16891,12 @@ init_err_dl:
init_err_pci_clean: init_err_pci_clean:
bnxt_hwrm_func_drv_unrgtr(bp); bnxt_hwrm_func_drv_unrgtr(bp);
bnxt_free_hwrm_resources(bp);
bnxt_hwmon_uninit(bp);
bnxt_ethtool_free(bp);
bnxt_ptp_clear(bp); bnxt_ptp_clear(bp);
kfree(bp->ptp_cfg); kfree(bp->ptp_cfg);
bp->ptp_cfg = NULL; bp->ptp_cfg = NULL;
bnxt_free_hwrm_resources(bp);
bnxt_hwmon_uninit(bp);
bnxt_ethtool_free(bp);
kfree(bp->fw_health); kfree(bp->fw_health);
bp->fw_health = NULL; bp->fw_health = NULL;
bnxt_cleanup_pci(bp); bnxt_cleanup_pci(bp);

View File

@ -1080,11 +1080,9 @@ struct bnxt_tpa_info {
struct rx_agg_cmp *agg_arr; struct rx_agg_cmp *agg_arr;
}; };
#define BNXT_AGG_IDX_BMAP_SIZE (MAX_TPA_P5 / BITS_PER_LONG)
struct bnxt_tpa_idx_map { struct bnxt_tpa_idx_map {
u16 agg_id_tbl[1024]; u16 agg_id_tbl[1024];
unsigned long agg_idx_bmap[BNXT_AGG_IDX_BMAP_SIZE]; DECLARE_BITMAP(agg_idx_bmap, MAX_TPA_P5);
}; };
struct bnxt_rx_ring_info { struct bnxt_rx_ring_info {

View File

@ -79,9 +79,9 @@ struct enetc_lso_t {
#define ENETC_RXB_TRUESIZE (PAGE_SIZE >> 1) #define ENETC_RXB_TRUESIZE (PAGE_SIZE >> 1)
#define ENETC_RXB_PAD NET_SKB_PAD /* add extra space if needed */ #define ENETC_RXB_PAD NET_SKB_PAD /* add extra space if needed */
#define ENETC_RXB_DMA_SIZE \ #define ENETC_RXB_DMA_SIZE \
(SKB_WITH_OVERHEAD(ENETC_RXB_TRUESIZE) - ENETC_RXB_PAD) min(SKB_WITH_OVERHEAD(ENETC_RXB_TRUESIZE) - ENETC_RXB_PAD, 0xffff)
#define ENETC_RXB_DMA_SIZE_XDP \ #define ENETC_RXB_DMA_SIZE_XDP \
(SKB_WITH_OVERHEAD(ENETC_RXB_TRUESIZE) - XDP_PACKET_HEADROOM) min(SKB_WITH_OVERHEAD(ENETC_RXB_TRUESIZE) - XDP_PACKET_HEADROOM, 0xffff)
struct enetc_rx_swbd { struct enetc_rx_swbd {
dma_addr_t dma; dma_addr_t dma;

View File

@ -284,8 +284,7 @@ struct idpf_port_stats {
struct idpf_fsteer_fltr { struct idpf_fsteer_fltr {
struct list_head list; struct list_head list;
u32 loc; struct ethtool_rx_flow_spec fs;
u32 q_index;
}; };
/** /**
@ -424,14 +423,12 @@ enum idpf_user_flags {
* @rss_key: RSS hash key * @rss_key: RSS hash key
* @rss_lut_size: Size of RSS lookup table * @rss_lut_size: Size of RSS lookup table
* @rss_lut: RSS lookup table * @rss_lut: RSS lookup table
* @cached_lut: Used to restore previously init RSS lut
*/ */
struct idpf_rss_data { struct idpf_rss_data {
u16 rss_key_size; u16 rss_key_size;
u8 *rss_key; u8 *rss_key;
u16 rss_lut_size; u16 rss_lut_size;
u32 *rss_lut; u32 *rss_lut;
u32 *cached_lut;
}; };
/** /**
@ -558,6 +555,7 @@ struct idpf_vector_lifo {
* @max_q: Maximum possible queues * @max_q: Maximum possible queues
* @req_qs_chunks: Queue chunk data for requested queues * @req_qs_chunks: Queue chunk data for requested queues
* @mac_filter_list_lock: Lock to protect mac filters * @mac_filter_list_lock: Lock to protect mac filters
* @flow_steer_list_lock: Lock to protect fsteer filters
* @flags: See enum idpf_vport_config_flags * @flags: See enum idpf_vport_config_flags
*/ */
struct idpf_vport_config { struct idpf_vport_config {
@ -565,6 +563,7 @@ struct idpf_vport_config {
struct idpf_vport_max_q max_q; struct idpf_vport_max_q max_q;
struct virtchnl2_add_queues *req_qs_chunks; struct virtchnl2_add_queues *req_qs_chunks;
spinlock_t mac_filter_list_lock; spinlock_t mac_filter_list_lock;
spinlock_t flow_steer_list_lock;
DECLARE_BITMAP(flags, IDPF_VPORT_CONFIG_FLAGS_NBITS); DECLARE_BITMAP(flags, IDPF_VPORT_CONFIG_FLAGS_NBITS);
}; };

View File

@ -37,6 +37,7 @@ static int idpf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
{ {
struct idpf_netdev_priv *np = netdev_priv(netdev); struct idpf_netdev_priv *np = netdev_priv(netdev);
struct idpf_vport_user_config_data *user_config; struct idpf_vport_user_config_data *user_config;
struct idpf_vport_config *vport_config;
struct idpf_fsteer_fltr *f; struct idpf_fsteer_fltr *f;
struct idpf_vport *vport; struct idpf_vport *vport;
unsigned int cnt = 0; unsigned int cnt = 0;
@ -44,7 +45,8 @@ static int idpf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
idpf_vport_ctrl_lock(netdev); idpf_vport_ctrl_lock(netdev);
vport = idpf_netdev_to_vport(netdev); vport = idpf_netdev_to_vport(netdev);
user_config = &np->adapter->vport_config[np->vport_idx]->user_config; vport_config = np->adapter->vport_config[np->vport_idx];
user_config = &vport_config->user_config;
switch (cmd->cmd) { switch (cmd->cmd) {
case ETHTOOL_GRXCLSRLCNT: case ETHTOOL_GRXCLSRLCNT:
@ -52,26 +54,34 @@ static int idpf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
cmd->data = idpf_fsteer_max_rules(vport); cmd->data = idpf_fsteer_max_rules(vport);
break; break;
case ETHTOOL_GRXCLSRULE: case ETHTOOL_GRXCLSRULE:
err = -EINVAL; err = -ENOENT;
spin_lock_bh(&vport_config->flow_steer_list_lock);
list_for_each_entry(f, &user_config->flow_steer_list, list) list_for_each_entry(f, &user_config->flow_steer_list, list)
if (f->loc == cmd->fs.location) { if (f->fs.location == cmd->fs.location) {
cmd->fs.ring_cookie = f->q_index; /* Avoid infoleak from padding: zero first,
* then assign fields
*/
memset(&cmd->fs, 0, sizeof(cmd->fs));
cmd->fs = f->fs;
err = 0; err = 0;
break; break;
} }
spin_unlock_bh(&vport_config->flow_steer_list_lock);
break; break;
case ETHTOOL_GRXCLSRLALL: case ETHTOOL_GRXCLSRLALL:
cmd->data = idpf_fsteer_max_rules(vport); cmd->data = idpf_fsteer_max_rules(vport);
spin_lock_bh(&vport_config->flow_steer_list_lock);
list_for_each_entry(f, &user_config->flow_steer_list, list) { list_for_each_entry(f, &user_config->flow_steer_list, list) {
if (cnt == cmd->rule_cnt) { if (cnt == cmd->rule_cnt) {
err = -EMSGSIZE; err = -EMSGSIZE;
break; break;
} }
rule_locs[cnt] = f->loc; rule_locs[cnt] = f->fs.location;
cnt++; cnt++;
} }
if (!err) if (!err)
cmd->rule_cnt = user_config->num_fsteer_fltrs; cmd->rule_cnt = user_config->num_fsteer_fltrs;
spin_unlock_bh(&vport_config->flow_steer_list_lock);
break; break;
default: default:
break; break;
@ -168,7 +178,7 @@ static int idpf_add_flow_steer(struct net_device *netdev,
struct idpf_vport *vport; struct idpf_vport *vport;
u32 flow_type, q_index; u32 flow_type, q_index;
u16 num_rxq; u16 num_rxq;
int err; int err = 0;
vport = idpf_netdev_to_vport(netdev); vport = idpf_netdev_to_vport(netdev);
vport_config = vport->adapter->vport_config[np->vport_idx]; vport_config = vport->adapter->vport_config[np->vport_idx];
@ -194,6 +204,29 @@ static int idpf_add_flow_steer(struct net_device *netdev,
if (!rule) if (!rule)
return -ENOMEM; return -ENOMEM;
fltr = kzalloc(sizeof(*fltr), GFP_KERNEL);
if (!fltr) {
err = -ENOMEM;
goto out_free_rule;
}
/* detect duplicate entry and reject before adding rules */
spin_lock_bh(&vport_config->flow_steer_list_lock);
list_for_each_entry(f, &user_config->flow_steer_list, list) {
if (f->fs.location == fsp->location) {
err = -EEXIST;
break;
}
if (f->fs.location > fsp->location)
break;
parent = f;
}
spin_unlock_bh(&vport_config->flow_steer_list_lock);
if (err)
goto out;
rule->vport_id = cpu_to_le32(vport->vport_id); rule->vport_id = cpu_to_le32(vport->vport_id);
rule->count = cpu_to_le32(1); rule->count = cpu_to_le32(1);
info = &rule->rule_info[0]; info = &rule->rule_info[0];
@ -232,26 +265,20 @@ static int idpf_add_flow_steer(struct net_device *netdev,
goto out; goto out;
} }
fltr = kzalloc(sizeof(*fltr), GFP_KERNEL); /* Save a copy of the user's flow spec so ethtool can later retrieve it */
if (!fltr) { fltr->fs = *fsp;
err = -ENOMEM;
goto out;
}
fltr->loc = fsp->location;
fltr->q_index = q_index;
list_for_each_entry(f, &user_config->flow_steer_list, list) {
if (f->loc >= fltr->loc)
break;
parent = f;
}
spin_lock_bh(&vport_config->flow_steer_list_lock);
parent ? list_add(&fltr->list, &parent->list) : parent ? list_add(&fltr->list, &parent->list) :
list_add(&fltr->list, &user_config->flow_steer_list); list_add(&fltr->list, &user_config->flow_steer_list);
user_config->num_fsteer_fltrs++; user_config->num_fsteer_fltrs++;
spin_unlock_bh(&vport_config->flow_steer_list_lock);
goto out_free_rule;
out: out:
kfree(fltr);
out_free_rule:
kfree(rule); kfree(rule);
return err; return err;
} }
@ -302,17 +329,20 @@ static int idpf_del_flow_steer(struct net_device *netdev,
goto out; goto out;
} }
spin_lock_bh(&vport_config->flow_steer_list_lock);
list_for_each_entry_safe(f, iter, list_for_each_entry_safe(f, iter,
&user_config->flow_steer_list, list) { &user_config->flow_steer_list, list) {
if (f->loc == fsp->location) { if (f->fs.location == fsp->location) {
list_del(&f->list); list_del(&f->list);
kfree(f); kfree(f);
user_config->num_fsteer_fltrs--; user_config->num_fsteer_fltrs--;
goto out; goto out_unlock;
} }
} }
err = -EINVAL; err = -ENOENT;
out_unlock:
spin_unlock_bh(&vport_config->flow_steer_list_lock);
out: out:
kfree(rule); kfree(rule);
return err; return err;
@ -381,7 +411,10 @@ static u32 idpf_get_rxfh_indir_size(struct net_device *netdev)
* @netdev: network interface device structure * @netdev: network interface device structure
* @rxfh: pointer to param struct (indir, key, hfunc) * @rxfh: pointer to param struct (indir, key, hfunc)
* *
* Reads the indirection table directly from the hardware. Always returns 0. * RSS LUT and Key information are read from driver's cached
* copy. When rxhash is off, rss lut will be displayed as zeros.
*
* Return: 0 on success, -errno otherwise.
*/ */
static int idpf_get_rxfh(struct net_device *netdev, static int idpf_get_rxfh(struct net_device *netdev,
struct ethtool_rxfh_param *rxfh) struct ethtool_rxfh_param *rxfh)
@ -389,10 +422,13 @@ static int idpf_get_rxfh(struct net_device *netdev,
struct idpf_netdev_priv *np = netdev_priv(netdev); struct idpf_netdev_priv *np = netdev_priv(netdev);
struct idpf_rss_data *rss_data; struct idpf_rss_data *rss_data;
struct idpf_adapter *adapter; struct idpf_adapter *adapter;
struct idpf_vport *vport;
bool rxhash_ena;
int err = 0; int err = 0;
u16 i; u16 i;
idpf_vport_ctrl_lock(netdev); idpf_vport_ctrl_lock(netdev);
vport = idpf_netdev_to_vport(netdev);
adapter = np->adapter; adapter = np->adapter;
@ -402,9 +438,8 @@ static int idpf_get_rxfh(struct net_device *netdev,
} }
rss_data = &adapter->vport_config[np->vport_idx]->user_config.rss_data; rss_data = &adapter->vport_config[np->vport_idx]->user_config.rss_data;
if (!test_bit(IDPF_VPORT_UP, np->state))
goto unlock_mutex;
rxhash_ena = idpf_is_feature_ena(vport, NETIF_F_RXHASH);
rxfh->hfunc = ETH_RSS_HASH_TOP; rxfh->hfunc = ETH_RSS_HASH_TOP;
if (rxfh->key) if (rxfh->key)
@ -412,7 +447,7 @@ static int idpf_get_rxfh(struct net_device *netdev,
if (rxfh->indir) { if (rxfh->indir) {
for (i = 0; i < rss_data->rss_lut_size; i++) for (i = 0; i < rss_data->rss_lut_size; i++)
rxfh->indir[i] = rss_data->rss_lut[i]; rxfh->indir[i] = rxhash_ena ? rss_data->rss_lut[i] : 0;
} }
unlock_mutex: unlock_mutex:
@ -452,8 +487,6 @@ static int idpf_set_rxfh(struct net_device *netdev,
} }
rss_data = &adapter->vport_config[vport->idx]->user_config.rss_data; rss_data = &adapter->vport_config[vport->idx]->user_config.rss_data;
if (!test_bit(IDPF_VPORT_UP, np->state))
goto unlock_mutex;
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
rxfh->hfunc != ETH_RSS_HASH_TOP) { rxfh->hfunc != ETH_RSS_HASH_TOP) {
@ -469,7 +502,8 @@ static int idpf_set_rxfh(struct net_device *netdev,
rss_data->rss_lut[lut] = rxfh->indir[lut]; rss_data->rss_lut[lut] = rxfh->indir[lut];
} }
err = idpf_config_rss(vport); if (test_bit(IDPF_VPORT_UP, np->state))
err = idpf_config_rss(vport);
unlock_mutex: unlock_mutex:
idpf_vport_ctrl_unlock(netdev); idpf_vport_ctrl_unlock(netdev);

View File

@ -322,7 +322,7 @@ static void idpf_idc_vport_dev_down(struct idpf_adapter *adapter)
for (i = 0; i < adapter->num_alloc_vports; i++) { for (i = 0; i < adapter->num_alloc_vports; i++) {
struct idpf_vport *vport = adapter->vports[i]; struct idpf_vport *vport = adapter->vports[i];
if (!vport) if (!vport || !vport->vdev_info)
continue; continue;
idpf_unplug_aux_dev(vport->vdev_info->adev); idpf_unplug_aux_dev(vport->vdev_info->adev);

View File

@ -442,6 +442,29 @@ send_dealloc_vecs:
return err; return err;
} }
/**
* idpf_del_all_flow_steer_filters - Delete all flow steer filters in list
* @vport: main vport struct
*
* Takes flow_steer_list_lock spinlock. Deletes all filters
*/
static void idpf_del_all_flow_steer_filters(struct idpf_vport *vport)
{
struct idpf_vport_config *vport_config;
struct idpf_fsteer_fltr *f, *ftmp;
vport_config = vport->adapter->vport_config[vport->idx];
spin_lock_bh(&vport_config->flow_steer_list_lock);
list_for_each_entry_safe(f, ftmp, &vport_config->user_config.flow_steer_list,
list) {
list_del(&f->list);
kfree(f);
}
vport_config->user_config.num_fsteer_fltrs = 0;
spin_unlock_bh(&vport_config->flow_steer_list_lock);
}
/** /**
* idpf_find_mac_filter - Search filter list for specific mac filter * idpf_find_mac_filter - Search filter list for specific mac filter
* @vconfig: Vport config structure * @vconfig: Vport config structure
@ -729,6 +752,65 @@ static int idpf_init_mac_addr(struct idpf_vport *vport,
return 0; return 0;
} }
static void idpf_detach_and_close(struct idpf_adapter *adapter)
{
int max_vports = adapter->max_vports;
for (int i = 0; i < max_vports; i++) {
struct net_device *netdev = adapter->netdevs[i];
/* If the interface is in detached state, that means the
* previous reset was not handled successfully for this
* vport.
*/
if (!netif_device_present(netdev))
continue;
/* Hold RTNL to protect racing with callbacks */
rtnl_lock();
netif_device_detach(netdev);
if (netif_running(netdev)) {
set_bit(IDPF_VPORT_UP_REQUESTED,
adapter->vport_config[i]->flags);
dev_close(netdev);
}
rtnl_unlock();
}
}
static void idpf_attach_and_open(struct idpf_adapter *adapter)
{
int max_vports = adapter->max_vports;
for (int i = 0; i < max_vports; i++) {
struct idpf_vport *vport = adapter->vports[i];
struct idpf_vport_config *vport_config;
struct net_device *netdev;
/* In case of a critical error in the init task, the vport
* will be freed. Only continue to restore the netdevs
* if the vport is allocated.
*/
if (!vport)
continue;
/* No need for RTNL on attach as this function is called
* following detach and dev_close(). We do take RTNL for
* dev_open() below as it can race with external callbacks
* following the call to netif_device_attach().
*/
netdev = adapter->netdevs[i];
netif_device_attach(netdev);
vport_config = adapter->vport_config[vport->idx];
if (test_and_clear_bit(IDPF_VPORT_UP_REQUESTED,
vport_config->flags)) {
rtnl_lock();
dev_open(netdev, NULL);
rtnl_unlock();
}
}
}
/** /**
* idpf_cfg_netdev - Allocate, configure and register a netdev * idpf_cfg_netdev - Allocate, configure and register a netdev
* @vport: main vport structure * @vport: main vport structure
@ -991,7 +1073,7 @@ static void idpf_vport_rel(struct idpf_vport *vport)
u16 idx = vport->idx; u16 idx = vport->idx;
vport_config = adapter->vport_config[vport->idx]; vport_config = adapter->vport_config[vport->idx];
idpf_deinit_rss(vport); idpf_deinit_rss_lut(vport);
rss_data = &vport_config->user_config.rss_data; rss_data = &vport_config->user_config.rss_data;
kfree(rss_data->rss_key); kfree(rss_data->rss_key);
rss_data->rss_key = NULL; rss_data->rss_key = NULL;
@ -1023,6 +1105,8 @@ static void idpf_vport_rel(struct idpf_vport *vport)
kfree(adapter->vport_config[idx]->req_qs_chunks); kfree(adapter->vport_config[idx]->req_qs_chunks);
adapter->vport_config[idx]->req_qs_chunks = NULL; adapter->vport_config[idx]->req_qs_chunks = NULL;
} }
kfree(vport->rx_ptype_lkup);
vport->rx_ptype_lkup = NULL;
kfree(vport); kfree(vport);
adapter->num_alloc_vports--; adapter->num_alloc_vports--;
} }
@ -1041,12 +1125,15 @@ static void idpf_vport_dealloc(struct idpf_vport *vport)
idpf_idc_deinit_vport_aux_device(vport->vdev_info); idpf_idc_deinit_vport_aux_device(vport->vdev_info);
idpf_deinit_mac_addr(vport); idpf_deinit_mac_addr(vport);
idpf_vport_stop(vport, true);
if (!test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags)) if (!test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags)) {
idpf_vport_stop(vport, true);
idpf_decfg_netdev(vport); idpf_decfg_netdev(vport);
if (test_bit(IDPF_REMOVE_IN_PROG, adapter->flags)) }
if (test_bit(IDPF_REMOVE_IN_PROG, adapter->flags)) {
idpf_del_all_mac_filters(vport); idpf_del_all_mac_filters(vport);
idpf_del_all_flow_steer_filters(vport);
}
if (adapter->netdevs[i]) { if (adapter->netdevs[i]) {
struct idpf_netdev_priv *np = netdev_priv(adapter->netdevs[i]); struct idpf_netdev_priv *np = netdev_priv(adapter->netdevs[i]);
@ -1139,6 +1226,7 @@ static struct idpf_vport *idpf_vport_alloc(struct idpf_adapter *adapter,
u16 idx = adapter->next_vport; u16 idx = adapter->next_vport;
struct idpf_vport *vport; struct idpf_vport *vport;
u16 num_max_q; u16 num_max_q;
int err;
if (idx == IDPF_NO_FREE_SLOT) if (idx == IDPF_NO_FREE_SLOT)
return NULL; return NULL;
@ -1189,10 +1277,11 @@ static struct idpf_vport *idpf_vport_alloc(struct idpf_adapter *adapter,
idpf_vport_init(vport, max_q); idpf_vport_init(vport, max_q);
/* This alloc is done separate from the LUT because it's not strictly /* LUT and key are both initialized here. Key is not strictly dependent
* dependent on how many queues we have. If we change number of queues * on how many queues we have. If we change number of queues and soft
* and soft reset we'll need a new LUT but the key can remain the same * reset is initiated, LUT will be freed and a new LUT will be allocated
* for as long as the vport exists. * as per the updated number of queues during vport bringup. However,
* the key remains the same for as long as the vport exists.
*/ */
rss_data = &adapter->vport_config[idx]->user_config.rss_data; rss_data = &adapter->vport_config[idx]->user_config.rss_data;
rss_data->rss_key = kzalloc(rss_data->rss_key_size, GFP_KERNEL); rss_data->rss_key = kzalloc(rss_data->rss_key_size, GFP_KERNEL);
@ -1202,6 +1291,11 @@ static struct idpf_vport *idpf_vport_alloc(struct idpf_adapter *adapter,
/* Initialize default rss key */ /* Initialize default rss key */
netdev_rss_key_fill((void *)rss_data->rss_key, rss_data->rss_key_size); netdev_rss_key_fill((void *)rss_data->rss_key, rss_data->rss_key_size);
/* Initialize default rss LUT */
err = idpf_init_rss_lut(vport);
if (err)
goto free_rss_key;
/* fill vport slot in the adapter struct */ /* fill vport slot in the adapter struct */
adapter->vports[idx] = vport; adapter->vports[idx] = vport;
adapter->vport_ids[idx] = idpf_get_vport_id(vport); adapter->vport_ids[idx] = idpf_get_vport_id(vport);
@ -1212,6 +1306,8 @@ static struct idpf_vport *idpf_vport_alloc(struct idpf_adapter *adapter,
return vport; return vport;
free_rss_key:
kfree(rss_data->rss_key);
free_vector_idxs: free_vector_idxs:
kfree(vport->q_vector_idxs); kfree(vport->q_vector_idxs);
free_vport: free_vport:
@ -1388,7 +1484,6 @@ static int idpf_vport_open(struct idpf_vport *vport, bool rtnl)
{ {
struct idpf_netdev_priv *np = netdev_priv(vport->netdev); struct idpf_netdev_priv *np = netdev_priv(vport->netdev);
struct idpf_adapter *adapter = vport->adapter; struct idpf_adapter *adapter = vport->adapter;
struct idpf_vport_config *vport_config;
int err; int err;
if (test_bit(IDPF_VPORT_UP, np->state)) if (test_bit(IDPF_VPORT_UP, np->state))
@ -1429,14 +1524,14 @@ static int idpf_vport_open(struct idpf_vport *vport, bool rtnl)
if (err) { if (err) {
dev_err(&adapter->pdev->dev, "Failed to initialize queue registers for vport %u: %d\n", dev_err(&adapter->pdev->dev, "Failed to initialize queue registers for vport %u: %d\n",
vport->vport_id, err); vport->vport_id, err);
goto queues_rel; goto intr_deinit;
} }
err = idpf_rx_bufs_init_all(vport); err = idpf_rx_bufs_init_all(vport);
if (err) { if (err) {
dev_err(&adapter->pdev->dev, "Failed to initialize RX buffers for vport %u: %d\n", dev_err(&adapter->pdev->dev, "Failed to initialize RX buffers for vport %u: %d\n",
vport->vport_id, err); vport->vport_id, err);
goto queues_rel; goto intr_deinit;
} }
idpf_rx_init_buf_tail(vport); idpf_rx_init_buf_tail(vport);
@ -1482,13 +1577,9 @@ static int idpf_vport_open(struct idpf_vport *vport, bool rtnl)
idpf_restore_features(vport); idpf_restore_features(vport);
vport_config = adapter->vport_config[vport->idx]; err = idpf_config_rss(vport);
if (vport_config->user_config.rss_data.rss_lut)
err = idpf_config_rss(vport);
else
err = idpf_init_rss(vport);
if (err) { if (err) {
dev_err(&adapter->pdev->dev, "Failed to initialize RSS for vport %u: %d\n", dev_err(&adapter->pdev->dev, "Failed to configure RSS for vport %u: %d\n",
vport->vport_id, err); vport->vport_id, err);
goto disable_vport; goto disable_vport;
} }
@ -1497,7 +1588,7 @@ static int idpf_vport_open(struct idpf_vport *vport, bool rtnl)
if (err) { if (err) {
dev_err(&adapter->pdev->dev, "Failed to complete interface up for vport %u: %d\n", dev_err(&adapter->pdev->dev, "Failed to complete interface up for vport %u: %d\n",
vport->vport_id, err); vport->vport_id, err);
goto deinit_rss; goto disable_vport;
} }
if (rtnl) if (rtnl)
@ -1505,8 +1596,6 @@ static int idpf_vport_open(struct idpf_vport *vport, bool rtnl)
return 0; return 0;
deinit_rss:
idpf_deinit_rss(vport);
disable_vport: disable_vport:
idpf_send_disable_vport_msg(vport); idpf_send_disable_vport_msg(vport);
disable_queues: disable_queues:
@ -1544,7 +1633,6 @@ void idpf_init_task(struct work_struct *work)
struct idpf_vport_config *vport_config; struct idpf_vport_config *vport_config;
struct idpf_vport_max_q max_q; struct idpf_vport_max_q max_q;
struct idpf_adapter *adapter; struct idpf_adapter *adapter;
struct idpf_netdev_priv *np;
struct idpf_vport *vport; struct idpf_vport *vport;
u16 num_default_vports; u16 num_default_vports;
struct pci_dev *pdev; struct pci_dev *pdev;
@ -1579,10 +1667,15 @@ void idpf_init_task(struct work_struct *work)
goto unwind_vports; goto unwind_vports;
} }
err = idpf_send_get_rx_ptype_msg(vport);
if (err)
goto unwind_vports;
index = vport->idx; index = vport->idx;
vport_config = adapter->vport_config[index]; vport_config = adapter->vport_config[index];
spin_lock_init(&vport_config->mac_filter_list_lock); spin_lock_init(&vport_config->mac_filter_list_lock);
spin_lock_init(&vport_config->flow_steer_list_lock);
INIT_LIST_HEAD(&vport_config->user_config.mac_filter_list); INIT_LIST_HEAD(&vport_config->user_config.mac_filter_list);
INIT_LIST_HEAD(&vport_config->user_config.flow_steer_list); INIT_LIST_HEAD(&vport_config->user_config.flow_steer_list);
@ -1590,21 +1683,11 @@ void idpf_init_task(struct work_struct *work)
err = idpf_check_supported_desc_ids(vport); err = idpf_check_supported_desc_ids(vport);
if (err) { if (err) {
dev_err(&pdev->dev, "failed to get required descriptor ids\n"); dev_err(&pdev->dev, "failed to get required descriptor ids\n");
goto cfg_netdev_err; goto unwind_vports;
} }
if (idpf_cfg_netdev(vport)) if (idpf_cfg_netdev(vport))
goto cfg_netdev_err; goto unwind_vports;
err = idpf_send_get_rx_ptype_msg(vport);
if (err)
goto handle_err;
/* Once state is put into DOWN, driver is ready for dev_open */
np = netdev_priv(vport->netdev);
clear_bit(IDPF_VPORT_UP, np->state);
if (test_and_clear_bit(IDPF_VPORT_UP_REQUESTED, vport_config->flags))
idpf_vport_open(vport, true);
/* Spawn and return 'idpf_init_task' work queue until all the /* Spawn and return 'idpf_init_task' work queue until all the
* default vports are created * default vports are created
@ -1635,21 +1718,15 @@ void idpf_init_task(struct work_struct *work)
set_bit(IDPF_VPORT_REG_NETDEV, vport_config->flags); set_bit(IDPF_VPORT_REG_NETDEV, vport_config->flags);
} }
/* As all the required vports are created, clear the reset flag /* Clear the reset and load bits as all vports are created */
* unconditionally here in case we were in reset and the link was down.
*/
clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags); clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
clear_bit(IDPF_HR_DRV_LOAD, adapter->flags);
/* Start the statistics task now */ /* Start the statistics task now */
queue_delayed_work(adapter->stats_wq, &adapter->stats_task, queue_delayed_work(adapter->stats_wq, &adapter->stats_task,
msecs_to_jiffies(10 * (pdev->devfn & 0x07))); msecs_to_jiffies(10 * (pdev->devfn & 0x07)));
return; return;
handle_err:
idpf_decfg_netdev(vport);
cfg_netdev_err:
idpf_vport_rel(vport);
adapter->vports[index] = NULL;
unwind_vports: unwind_vports:
if (default_vport) { if (default_vport) {
for (index = 0; index < adapter->max_vports; index++) { for (index = 0; index < adapter->max_vports; index++) {
@ -1657,6 +1734,15 @@ unwind_vports:
idpf_vport_dealloc(adapter->vports[index]); idpf_vport_dealloc(adapter->vports[index]);
} }
} }
/* Cleanup after vc_core_init, which has no way of knowing the
* init task failed on driver load.
*/
if (test_and_clear_bit(IDPF_HR_DRV_LOAD, adapter->flags)) {
cancel_delayed_work_sync(&adapter->serv_task);
cancel_delayed_work_sync(&adapter->mbx_task);
}
idpf_ptp_release(adapter);
clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags); clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
} }
@ -1786,27 +1872,6 @@ static int idpf_check_reset_complete(struct idpf_hw *hw,
return -EBUSY; return -EBUSY;
} }
/**
* idpf_set_vport_state - Set the vport state to be after the reset
* @adapter: Driver specific private structure
*/
static void idpf_set_vport_state(struct idpf_adapter *adapter)
{
u16 i;
for (i = 0; i < adapter->max_vports; i++) {
struct idpf_netdev_priv *np;
if (!adapter->netdevs[i])
continue;
np = netdev_priv(adapter->netdevs[i]);
if (test_bit(IDPF_VPORT_UP, np->state))
set_bit(IDPF_VPORT_UP_REQUESTED,
adapter->vport_config[i]->flags);
}
}
/** /**
* idpf_init_hard_reset - Initiate a hardware reset * idpf_init_hard_reset - Initiate a hardware reset
* @adapter: Driver specific private structure * @adapter: Driver specific private structure
@ -1815,37 +1880,25 @@ static void idpf_set_vport_state(struct idpf_adapter *adapter)
* reallocate. Also reinitialize the mailbox. Return 0 on success, * reallocate. Also reinitialize the mailbox. Return 0 on success,
* negative on failure. * negative on failure.
*/ */
static int idpf_init_hard_reset(struct idpf_adapter *adapter) static void idpf_init_hard_reset(struct idpf_adapter *adapter)
{ {
struct idpf_reg_ops *reg_ops = &adapter->dev_ops.reg_ops; struct idpf_reg_ops *reg_ops = &adapter->dev_ops.reg_ops;
struct device *dev = &adapter->pdev->dev; struct device *dev = &adapter->pdev->dev;
struct net_device *netdev;
int err; int err;
u16 i;
idpf_detach_and_close(adapter);
mutex_lock(&adapter->vport_ctrl_lock); mutex_lock(&adapter->vport_ctrl_lock);
dev_info(dev, "Device HW Reset initiated\n"); dev_info(dev, "Device HW Reset initiated\n");
/* Avoid TX hangs on reset */
for (i = 0; i < adapter->max_vports; i++) {
netdev = adapter->netdevs[i];
if (!netdev)
continue;
netif_carrier_off(netdev);
netif_tx_disable(netdev);
}
/* Prepare for reset */ /* Prepare for reset */
if (test_and_clear_bit(IDPF_HR_DRV_LOAD, adapter->flags)) { if (test_bit(IDPF_HR_DRV_LOAD, adapter->flags)) {
reg_ops->trigger_reset(adapter, IDPF_HR_DRV_LOAD); reg_ops->trigger_reset(adapter, IDPF_HR_DRV_LOAD);
} else if (test_and_clear_bit(IDPF_HR_FUNC_RESET, adapter->flags)) { } else if (test_and_clear_bit(IDPF_HR_FUNC_RESET, adapter->flags)) {
bool is_reset = idpf_is_reset_detected(adapter); bool is_reset = idpf_is_reset_detected(adapter);
idpf_idc_issue_reset_event(adapter->cdev_info); idpf_idc_issue_reset_event(adapter->cdev_info);
idpf_set_vport_state(adapter);
idpf_vc_core_deinit(adapter); idpf_vc_core_deinit(adapter);
if (!is_reset) if (!is_reset)
reg_ops->trigger_reset(adapter, IDPF_HR_FUNC_RESET); reg_ops->trigger_reset(adapter, IDPF_HR_FUNC_RESET);
@ -1892,11 +1945,14 @@ static int idpf_init_hard_reset(struct idpf_adapter *adapter)
unlock_mutex: unlock_mutex:
mutex_unlock(&adapter->vport_ctrl_lock); mutex_unlock(&adapter->vport_ctrl_lock);
/* Wait until all vports are created to init RDMA CORE AUX */ /* Attempt to restore netdevs and initialize RDMA CORE AUX device,
if (!err) * provided vc_core_init succeeded. It is still possible that
err = idpf_idc_init(adapter); * vports are not allocated at this point if the init task failed.
*/
return err; if (!err) {
idpf_attach_and_open(adapter);
idpf_idc_init(adapter);
}
} }
/** /**
@ -1997,7 +2053,6 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
idpf_vport_stop(vport, false); idpf_vport_stop(vport, false);
} }
idpf_deinit_rss(vport);
/* We're passing in vport here because we need its wait_queue /* We're passing in vport here because we need its wait_queue
* to send a message and it should be getting all the vport * to send a message and it should be getting all the vport
* config data out of the adapter but we need to be careful not * config data out of the adapter but we need to be careful not
@ -2023,6 +2078,10 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
if (err) if (err)
goto err_open; goto err_open;
if (reset_cause == IDPF_SR_Q_CHANGE &&
!netif_is_rxfh_configured(vport->netdev))
idpf_fill_dflt_rss_lut(vport);
if (vport_is_up) if (vport_is_up)
err = idpf_vport_open(vport, false); err = idpf_vport_open(vport, false);
@ -2165,40 +2224,6 @@ static void idpf_set_rx_mode(struct net_device *netdev)
dev_err(dev, "Failed to set promiscuous mode: %d\n", err); dev_err(dev, "Failed to set promiscuous mode: %d\n", err);
} }
/**
* idpf_vport_manage_rss_lut - disable/enable RSS
* @vport: the vport being changed
*
* In the event of disable request for RSS, this function will zero out RSS
* LUT, while in the event of enable request for RSS, it will reconfigure RSS
* LUT with the default LUT configuration.
*/
static int idpf_vport_manage_rss_lut(struct idpf_vport *vport)
{
bool ena = idpf_is_feature_ena(vport, NETIF_F_RXHASH);
struct idpf_rss_data *rss_data;
u16 idx = vport->idx;
int lut_size;
rss_data = &vport->adapter->vport_config[idx]->user_config.rss_data;
lut_size = rss_data->rss_lut_size * sizeof(u32);
if (ena) {
/* This will contain the default or user configured LUT */
memcpy(rss_data->rss_lut, rss_data->cached_lut, lut_size);
} else {
/* Save a copy of the current LUT to be restored later if
* requested.
*/
memcpy(rss_data->cached_lut, rss_data->rss_lut, lut_size);
/* Zero out the current LUT to disable */
memset(rss_data->rss_lut, 0, lut_size);
}
return idpf_config_rss(vport);
}
/** /**
* idpf_set_features - set the netdev feature flags * idpf_set_features - set the netdev feature flags
* @netdev: ptr to the netdev being adjusted * @netdev: ptr to the netdev being adjusted
@ -2224,10 +2249,19 @@ static int idpf_set_features(struct net_device *netdev,
} }
if (changed & NETIF_F_RXHASH) { if (changed & NETIF_F_RXHASH) {
struct idpf_netdev_priv *np = netdev_priv(netdev);
netdev->features ^= NETIF_F_RXHASH; netdev->features ^= NETIF_F_RXHASH;
err = idpf_vport_manage_rss_lut(vport);
if (err) /* If the interface is not up when changing the rxhash, update
goto unlock_mutex; * to the HW is skipped. The updated LUT will be committed to
* the HW when the interface is brought up.
*/
if (test_bit(IDPF_VPORT_UP, np->state)) {
err = idpf_config_rss(vport);
if (err)
goto unlock_mutex;
}
} }
if (changed & NETIF_F_GRO_HW) { if (changed & NETIF_F_GRO_HW) {

View File

@ -695,9 +695,10 @@ err:
static int idpf_rx_bufs_init_singleq(struct idpf_rx_queue *rxq) static int idpf_rx_bufs_init_singleq(struct idpf_rx_queue *rxq)
{ {
struct libeth_fq fq = { struct libeth_fq fq = {
.count = rxq->desc_count, .count = rxq->desc_count,
.type = LIBETH_FQE_MTU, .type = LIBETH_FQE_MTU,
.nid = idpf_q_vector_to_mem(rxq->q_vector), .buf_len = IDPF_RX_MAX_BUF_SZ,
.nid = idpf_q_vector_to_mem(rxq->q_vector),
}; };
int ret; int ret;
@ -754,6 +755,7 @@ static int idpf_rx_bufs_init(struct idpf_buf_queue *bufq,
.truesize = bufq->truesize, .truesize = bufq->truesize,
.count = bufq->desc_count, .count = bufq->desc_count,
.type = type, .type = type,
.buf_len = IDPF_RX_MAX_BUF_SZ,
.hsplit = idpf_queue_has(HSPLIT_EN, bufq), .hsplit = idpf_queue_has(HSPLIT_EN, bufq),
.xdp = idpf_xdp_enabled(bufq->q_vector->vport), .xdp = idpf_xdp_enabled(bufq->q_vector->vport),
.nid = idpf_q_vector_to_mem(bufq->q_vector), .nid = idpf_q_vector_to_mem(bufq->q_vector),
@ -4641,7 +4643,7 @@ int idpf_config_rss(struct idpf_vport *vport)
* idpf_fill_dflt_rss_lut - Fill the indirection table with the default values * idpf_fill_dflt_rss_lut - Fill the indirection table with the default values
* @vport: virtual port structure * @vport: virtual port structure
*/ */
static void idpf_fill_dflt_rss_lut(struct idpf_vport *vport) void idpf_fill_dflt_rss_lut(struct idpf_vport *vport)
{ {
struct idpf_adapter *adapter = vport->adapter; struct idpf_adapter *adapter = vport->adapter;
u16 num_active_rxq = vport->num_rxq; u16 num_active_rxq = vport->num_rxq;
@ -4650,57 +4652,47 @@ static void idpf_fill_dflt_rss_lut(struct idpf_vport *vport)
rss_data = &adapter->vport_config[vport->idx]->user_config.rss_data; rss_data = &adapter->vport_config[vport->idx]->user_config.rss_data;
for (i = 0; i < rss_data->rss_lut_size; i++) { for (i = 0; i < rss_data->rss_lut_size; i++)
rss_data->rss_lut[i] = i % num_active_rxq; rss_data->rss_lut[i] = i % num_active_rxq;
rss_data->cached_lut[i] = rss_data->rss_lut[i];
}
} }
/** /**
* idpf_init_rss - Allocate and initialize RSS resources * idpf_init_rss_lut - Allocate and initialize RSS LUT
* @vport: virtual port * @vport: virtual port
* *
* Return 0 on success, negative on failure * Return: 0 on success, negative on failure
*/ */
int idpf_init_rss(struct idpf_vport *vport) int idpf_init_rss_lut(struct idpf_vport *vport)
{ {
struct idpf_adapter *adapter = vport->adapter; struct idpf_adapter *adapter = vport->adapter;
struct idpf_rss_data *rss_data; struct idpf_rss_data *rss_data;
u32 lut_size;
rss_data = &adapter->vport_config[vport->idx]->user_config.rss_data; rss_data = &adapter->vport_config[vport->idx]->user_config.rss_data;
if (!rss_data->rss_lut) {
u32 lut_size;
lut_size = rss_data->rss_lut_size * sizeof(u32); lut_size = rss_data->rss_lut_size * sizeof(u32);
rss_data->rss_lut = kzalloc(lut_size, GFP_KERNEL); rss_data->rss_lut = kzalloc(lut_size, GFP_KERNEL);
if (!rss_data->rss_lut) if (!rss_data->rss_lut)
return -ENOMEM; return -ENOMEM;
rss_data->cached_lut = kzalloc(lut_size, GFP_KERNEL);
if (!rss_data->cached_lut) {
kfree(rss_data->rss_lut);
rss_data->rss_lut = NULL;
return -ENOMEM;
} }
/* Fill the default RSS lut values */ /* Fill the default RSS lut values */
idpf_fill_dflt_rss_lut(vport); idpf_fill_dflt_rss_lut(vport);
return idpf_config_rss(vport); return 0;
} }
/** /**
* idpf_deinit_rss - Release RSS resources * idpf_deinit_rss_lut - Release RSS LUT
* @vport: virtual port * @vport: virtual port
*/ */
void idpf_deinit_rss(struct idpf_vport *vport) void idpf_deinit_rss_lut(struct idpf_vport *vport)
{ {
struct idpf_adapter *adapter = vport->adapter; struct idpf_adapter *adapter = vport->adapter;
struct idpf_rss_data *rss_data; struct idpf_rss_data *rss_data;
rss_data = &adapter->vport_config[vport->idx]->user_config.rss_data; rss_data = &adapter->vport_config[vport->idx]->user_config.rss_data;
kfree(rss_data->cached_lut);
rss_data->cached_lut = NULL;
kfree(rss_data->rss_lut); kfree(rss_data->rss_lut);
rss_data->rss_lut = NULL; rss_data->rss_lut = NULL;
} }

View File

@ -101,6 +101,7 @@ do { \
idx = 0; \ idx = 0; \
} while (0) } while (0)
#define IDPF_RX_MAX_BUF_SZ (16384 - 128)
#define IDPF_RX_BUF_STRIDE 32 #define IDPF_RX_BUF_STRIDE 32
#define IDPF_RX_BUF_POST_STRIDE 16 #define IDPF_RX_BUF_POST_STRIDE 16
#define IDPF_LOW_WATERMARK 64 #define IDPF_LOW_WATERMARK 64
@ -1085,9 +1086,10 @@ void idpf_vport_intr_update_itr_ena_irq(struct idpf_q_vector *q_vector);
void idpf_vport_intr_deinit(struct idpf_vport *vport); void idpf_vport_intr_deinit(struct idpf_vport *vport);
int idpf_vport_intr_init(struct idpf_vport *vport); int idpf_vport_intr_init(struct idpf_vport *vport);
void idpf_vport_intr_ena(struct idpf_vport *vport); void idpf_vport_intr_ena(struct idpf_vport *vport);
void idpf_fill_dflt_rss_lut(struct idpf_vport *vport);
int idpf_config_rss(struct idpf_vport *vport); int idpf_config_rss(struct idpf_vport *vport);
int idpf_init_rss(struct idpf_vport *vport); int idpf_init_rss_lut(struct idpf_vport *vport);
void idpf_deinit_rss(struct idpf_vport *vport); void idpf_deinit_rss_lut(struct idpf_vport *vport);
int idpf_rx_bufs_init_all(struct idpf_vport *vport); int idpf_rx_bufs_init_all(struct idpf_vport *vport);
struct idpf_q_vector *idpf_find_rxq_vec(const struct idpf_vport *vport, struct idpf_q_vector *idpf_find_rxq_vec(const struct idpf_vport *vport,

View File

@ -2804,6 +2804,10 @@ int idpf_send_get_stats_msg(struct idpf_vport *vport)
* @vport: virtual port data structure * @vport: virtual port data structure
* @get: flag to set or get rss look up table * @get: flag to set or get rss look up table
* *
* When rxhash is disabled, RSS LUT will be configured with zeros. If rxhash
* is enabled, the LUT values stored in driver's soft copy will be used to setup
* the HW.
*
* Returns 0 on success, negative on failure. * Returns 0 on success, negative on failure.
*/ */
int idpf_send_get_set_rss_lut_msg(struct idpf_vport *vport, bool get) int idpf_send_get_set_rss_lut_msg(struct idpf_vport *vport, bool get)
@ -2814,10 +2818,12 @@ int idpf_send_get_set_rss_lut_msg(struct idpf_vport *vport, bool get)
struct idpf_rss_data *rss_data; struct idpf_rss_data *rss_data;
int buf_size, lut_buf_size; int buf_size, lut_buf_size;
ssize_t reply_sz; ssize_t reply_sz;
bool rxhash_ena;
int i; int i;
rss_data = rss_data =
&vport->adapter->vport_config[vport->idx]->user_config.rss_data; &vport->adapter->vport_config[vport->idx]->user_config.rss_data;
rxhash_ena = idpf_is_feature_ena(vport, NETIF_F_RXHASH);
buf_size = struct_size(rl, lut, rss_data->rss_lut_size); buf_size = struct_size(rl, lut, rss_data->rss_lut_size);
rl = kzalloc(buf_size, GFP_KERNEL); rl = kzalloc(buf_size, GFP_KERNEL);
if (!rl) if (!rl)
@ -2839,7 +2845,8 @@ int idpf_send_get_set_rss_lut_msg(struct idpf_vport *vport, bool get)
} else { } else {
rl->lut_entries = cpu_to_le16(rss_data->rss_lut_size); rl->lut_entries = cpu_to_le16(rss_data->rss_lut_size);
for (i = 0; i < rss_data->rss_lut_size; i++) for (i = 0; i < rss_data->rss_lut_size; i++)
rl->lut[i] = cpu_to_le32(rss_data->rss_lut[i]); rl->lut[i] = rxhash_ena ?
cpu_to_le32(rss_data->rss_lut[i]) : 0;
xn_params.vc_op = VIRTCHNL2_OP_SET_RSS_LUT; xn_params.vc_op = VIRTCHNL2_OP_SET_RSS_LUT;
} }
@ -3570,6 +3577,7 @@ init_failed:
*/ */
void idpf_vc_core_deinit(struct idpf_adapter *adapter) void idpf_vc_core_deinit(struct idpf_adapter *adapter)
{ {
struct idpf_hw *hw = &adapter->hw;
bool remove_in_prog; bool remove_in_prog;
if (!test_bit(IDPF_VC_CORE_INIT, adapter->flags)) if (!test_bit(IDPF_VC_CORE_INIT, adapter->flags))
@ -3593,6 +3601,9 @@ void idpf_vc_core_deinit(struct idpf_adapter *adapter)
idpf_vport_params_buf_rel(adapter); idpf_vport_params_buf_rel(adapter);
kfree(hw->lan_regs);
hw->lan_regs = NULL;
kfree(adapter->vports); kfree(adapter->vports);
adapter->vports = NULL; adapter->vports = NULL;

View File

@ -387,6 +387,8 @@ struct prestera_switch *prestera_devlink_alloc(struct prestera_device *dev)
dl = devlink_alloc(&prestera_dl_ops, sizeof(struct prestera_switch), dl = devlink_alloc(&prestera_dl_ops, sizeof(struct prestera_switch),
dev->dev); dev->dev);
if (!dl)
return NULL;
return devlink_priv(dl); return devlink_priv(dl);
} }

View File

@ -44,6 +44,7 @@ struct mlx5e_accel_fs_psp_prot {
struct mlx5_flow_table *ft; struct mlx5_flow_table *ft;
struct mlx5_flow_group *miss_group; struct mlx5_flow_group *miss_group;
struct mlx5_flow_handle *miss_rule; struct mlx5_flow_handle *miss_rule;
struct mlx5_modify_hdr *rx_modify_hdr;
struct mlx5_flow_destination default_dest; struct mlx5_flow_destination default_dest;
struct mlx5e_psp_rx_err rx_err; struct mlx5e_psp_rx_err rx_err;
u32 refcnt; u32 refcnt;
@ -286,13 +287,19 @@ out_err:
return err; return err;
} }
static void accel_psp_fs_rx_fs_destroy(struct mlx5e_accel_fs_psp_prot *fs_prot) static void accel_psp_fs_rx_fs_destroy(struct mlx5e_psp_fs *fs,
struct mlx5e_accel_fs_psp_prot *fs_prot)
{ {
if (fs_prot->def_rule) { if (fs_prot->def_rule) {
mlx5_del_flow_rules(fs_prot->def_rule); mlx5_del_flow_rules(fs_prot->def_rule);
fs_prot->def_rule = NULL; fs_prot->def_rule = NULL;
} }
if (fs_prot->rx_modify_hdr) {
mlx5_modify_header_dealloc(fs->mdev, fs_prot->rx_modify_hdr);
fs_prot->rx_modify_hdr = NULL;
}
if (fs_prot->miss_rule) { if (fs_prot->miss_rule) {
mlx5_del_flow_rules(fs_prot->miss_rule); mlx5_del_flow_rules(fs_prot->miss_rule);
fs_prot->miss_rule = NULL; fs_prot->miss_rule = NULL;
@ -396,6 +403,7 @@ static int accel_psp_fs_rx_create_ft(struct mlx5e_psp_fs *fs,
modify_hdr = NULL; modify_hdr = NULL;
goto out_err; goto out_err;
} }
fs_prot->rx_modify_hdr = modify_hdr;
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT | MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT |
@ -416,7 +424,7 @@ static int accel_psp_fs_rx_create_ft(struct mlx5e_psp_fs *fs,
goto out; goto out;
out_err: out_err:
accel_psp_fs_rx_fs_destroy(fs_prot); accel_psp_fs_rx_fs_destroy(fs, fs_prot);
out: out:
kvfree(flow_group_in); kvfree(flow_group_in);
kvfree(spec); kvfree(spec);
@ -433,7 +441,7 @@ static int accel_psp_fs_rx_destroy(struct mlx5e_psp_fs *fs, enum accel_fs_psp_ty
/* The netdev unreg already happened, so all offloaded rule are already removed */ /* The netdev unreg already happened, so all offloaded rule are already removed */
fs_prot = &accel_psp->fs_prot[type]; fs_prot = &accel_psp->fs_prot[type];
accel_psp_fs_rx_fs_destroy(fs_prot); accel_psp_fs_rx_fs_destroy(fs, fs_prot);
accel_psp_fs_rx_err_destroy_ft(fs, &fs_prot->rx_err); accel_psp_fs_rx_err_destroy_ft(fs, &fs_prot->rx_err);

View File

@ -1608,12 +1608,13 @@ void mlx5e_stats_fec_get(struct mlx5e_priv *priv,
{ {
int mode = fec_active_mode(priv->mdev); int mode = fec_active_mode(priv->mdev);
if (mode == MLX5E_FEC_NOFEC || if (mode == MLX5E_FEC_NOFEC)
!MLX5_CAP_PCAM_FEATURE(priv->mdev, ppcnt_statistical_group))
return; return;
fec_set_corrected_bits_total(priv, fec_stats); if (MLX5_CAP_PCAM_FEATURE(priv->mdev, ppcnt_statistical_group)) {
fec_set_block_stats(priv, mode, fec_stats); fec_set_corrected_bits_total(priv, fec_stats);
fec_set_block_stats(priv, mode, fec_stats);
}
if (MLX5_CAP_PCAM_REG(priv->mdev, pphcr)) if (MLX5_CAP_PCAM_REG(priv->mdev, pphcr))
fec_set_histograms_stats(priv, mode, hist); fec_set_histograms_stats(priv, mode, hist);

View File

@ -173,10 +173,15 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event,
} }
/* Handle multipath entry with lower priority value */ /* Handle multipath entry with lower priority value */
if (mp->fib.mfi && mp->fib.mfi != fi && if (mp->fib.mfi &&
(mp->fib.dst != fen_info->dst || mp->fib.dst_len != fen_info->dst_len) && (mp->fib.dst != fen_info->dst || mp->fib.dst_len != fen_info->dst_len) &&
fi->fib_priority >= mp->fib.priority) mp->fib.dst_len <= fen_info->dst_len &&
!(mp->fib.dst_len == fen_info->dst_len &&
fi->fib_priority < mp->fib.priority)) {
mlx5_core_dbg(ldev->pf[idx].dev,
"Multipath entry with lower priority was rejected\n");
return; return;
}
nh_dev0 = mlx5_lag_get_next_fib_dev(ldev, fi, NULL); nh_dev0 = mlx5_lag_get_next_fib_dev(ldev, fi, NULL);
nh_dev1 = mlx5_lag_get_next_fib_dev(ldev, fi, nh_dev0); nh_dev1 = mlx5_lag_get_next_fib_dev(ldev, fi, nh_dev0);

View File

@ -393,9 +393,11 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev,
if (err) if (err)
return err; return err;
*status = MLX5_GET(mcia_reg, out, status); if (MLX5_GET(mcia_reg, out, status)) {
if (*status) if (status)
*status = MLX5_GET(mcia_reg, out, status);
return -EIO; return -EIO;
}
ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
memcpy(data, ptr, size); memcpy(data, ptr, size);
@ -429,7 +431,8 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
mlx5_qsfp_eeprom_params_set(&query.i2c_address, &query.page, &offset); mlx5_qsfp_eeprom_params_set(&query.i2c_address, &query.page, &offset);
break; break;
default: default:
mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id); mlx5_core_dbg(dev, "Module ID not recognized: 0x%x\n",
module_id);
return -EINVAL; return -EINVAL;
} }

View File

@ -2307,14 +2307,16 @@ static void ocelot_set_aggr_pgids(struct ocelot *ocelot)
/* Now, set PGIDs for each active LAG */ /* Now, set PGIDs for each active LAG */
for (lag = 0; lag < ocelot->num_phys_ports; lag++) { for (lag = 0; lag < ocelot->num_phys_ports; lag++) {
struct net_device *bond = ocelot->ports[lag]->bond; struct ocelot_port *ocelot_port = ocelot->ports[lag];
int num_active_ports = 0; int num_active_ports = 0;
struct net_device *bond;
unsigned long bond_mask; unsigned long bond_mask;
u8 aggr_idx[16]; u8 aggr_idx[16];
if (!bond || (visited & BIT(lag))) if (!ocelot_port || !ocelot_port->bond || (visited & BIT(lag)))
continue; continue;
bond = ocelot_port->bond;
bond_mask = ocelot_get_bond_mask(ocelot, bond); bond_mask = ocelot_get_bond_mask(ocelot, bond);
for_each_set_bit(port, &bond_mask, ocelot->num_phys_ports) { for_each_set_bit(port, &bond_mask, ocelot->num_phys_ports) {

View File

@ -332,6 +332,11 @@ static ssize_t link_device_store(const struct bus_type *bus, const char *buf, si
rcu_assign_pointer(nsim_a->peer, nsim_b); rcu_assign_pointer(nsim_a->peer, nsim_b);
rcu_assign_pointer(nsim_b->peer, nsim_a); rcu_assign_pointer(nsim_b->peer, nsim_a);
if (netif_running(dev_a) && netif_running(dev_b)) {
netif_carrier_on(dev_a);
netif_carrier_on(dev_b);
}
out_err: out_err:
put_net(ns_b); put_net(ns_b);
put_net(ns_a); put_net(ns_a);
@ -381,6 +386,9 @@ static ssize_t unlink_device_store(const struct bus_type *bus, const char *buf,
if (!peer) if (!peer)
goto out_put_netns; goto out_put_netns;
netif_carrier_off(dev);
netif_carrier_off(peer->netdev);
err = 0; err = 0;
RCU_INIT_POINTER(nsim->peer, NULL); RCU_INIT_POINTER(nsim->peer, NULL);
RCU_INIT_POINTER(peer->peer, NULL); RCU_INIT_POINTER(peer->peer, NULL);

View File

@ -938,6 +938,9 @@ static struct phy_driver mxl_phy_drvs[] = {
PHY_ID_MATCH_EXACT(PHY_ID_MXL86110), PHY_ID_MATCH_EXACT(PHY_ID_MXL86110),
.name = "MXL86110 Gigabit Ethernet", .name = "MXL86110 Gigabit Ethernet",
.config_init = mxl86110_config_init, .config_init = mxl86110_config_init,
.suspend = genphy_suspend,
.resume = genphy_resume,
.soft_reset = genphy_soft_reset,
.get_wol = mxl86110_get_wol, .get_wol = mxl86110_get_wol,
.set_wol = mxl86110_set_wol, .set_wol = mxl86110_set_wol,
.led_brightness_set = mxl86110_led_brightness_set, .led_brightness_set = mxl86110_led_brightness_set,

View File

@ -765,7 +765,7 @@ static int sfp_smbus_byte_write(struct sfp *sfp, bool a2, u8 dev_addr,
dev_addr++; dev_addr++;
} }
return 0; return data - (u8 *)buf;
} }
static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c) static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)

View File

@ -168,6 +168,8 @@ static int update_eth_regs_async(pegasus_t *pegasus)
netif_device_detach(pegasus->net); netif_device_detach(pegasus->net);
netif_err(pegasus, drv, pegasus->net, netif_err(pegasus, drv, pegasus->net,
"%s returned %d\n", __func__, ret); "%s returned %d\n", __func__, ret);
usb_free_urb(async_urb);
kfree(req);
} }
return ret; return ret;
} }

View File

@ -3791,7 +3791,7 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
if (vi->has_rss && !netif_is_rxfh_configured(dev)) { if (vi->has_rss && !netif_is_rxfh_configured(dev)) {
old_rss_hdr = vi->rss_hdr; old_rss_hdr = vi->rss_hdr;
old_rss_trailer = vi->rss_trailer; old_rss_trailer = vi->rss_trailer;
vi->rss_hdr = devm_kzalloc(&dev->dev, virtnet_rss_hdr_size(vi), GFP_KERNEL); vi->rss_hdr = devm_kzalloc(&vi->vdev->dev, virtnet_rss_hdr_size(vi), GFP_KERNEL);
if (!vi->rss_hdr) { if (!vi->rss_hdr) {
vi->rss_hdr = old_rss_hdr; vi->rss_hdr = old_rss_hdr;
return -ENOMEM; return -ENOMEM;
@ -3802,7 +3802,7 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
if (!virtnet_commit_rss_command(vi)) { if (!virtnet_commit_rss_command(vi)) {
/* restore ctrl_rss if commit_rss_command failed */ /* restore ctrl_rss if commit_rss_command failed */
devm_kfree(&dev->dev, vi->rss_hdr); devm_kfree(&vi->vdev->dev, vi->rss_hdr);
vi->rss_hdr = old_rss_hdr; vi->rss_hdr = old_rss_hdr;
vi->rss_trailer = old_rss_trailer; vi->rss_trailer = old_rss_trailer;
@ -3810,7 +3810,7 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
queue_pairs); queue_pairs);
return -EINVAL; return -EINVAL;
} }
devm_kfree(&dev->dev, old_rss_hdr); devm_kfree(&vi->vdev->dev, old_rss_hdr);
goto succ; goto succ;
} }

View File

@ -4040,7 +4040,7 @@ mac80211_hwsim_nan_dw_start(struct hrtimer *timer)
ieee80211_vif_to_wdev(data->nan_device_vif); ieee80211_vif_to_wdev(data->nan_device_vif);
if (data->nan_curr_dw_band == NL80211_BAND_5GHZ) if (data->nan_curr_dw_band == NL80211_BAND_5GHZ)
ch = ieee80211_get_channel(hw->wiphy, 5475); ch = ieee80211_get_channel(hw->wiphy, 5745);
else else
ch = ieee80211_get_channel(hw->wiphy, 2437); ch = ieee80211_get_channel(hw->wiphy, 2437);
@ -4112,14 +4112,14 @@ static int mac80211_hwsim_stop_nan(struct ieee80211_hw *hw,
hrtimer_cancel(&data->nan_timer); hrtimer_cancel(&data->nan_timer);
data->nan_device_vif = NULL; data->nan_device_vif = NULL;
spin_lock(&hwsim_radio_lock); spin_lock_bh(&hwsim_radio_lock);
list_for_each_entry(data2, &hwsim_radios, list) { list_for_each_entry(data2, &hwsim_radios, list) {
if (data2->nan_device_vif) { if (data2->nan_device_vif) {
nan_cluster_running = true; nan_cluster_running = true;
break; break;
} }
} }
spin_unlock(&hwsim_radio_lock); spin_unlock_bh(&hwsim_radio_lock);
if (!nan_cluster_running) if (!nan_cluster_running)
memset(hwsim_nan_cluster_id, 0, ETH_ALEN); memset(hwsim_nan_cluster_id, 0, ETH_ALEN);

View File

@ -456,6 +456,7 @@ void ipc_mux_deinit(struct iosm_mux *ipc_mux)
struct sk_buff_head *free_list; struct sk_buff_head *free_list;
union mux_msg mux_msg; union mux_msg mux_msg;
struct sk_buff *skb; struct sk_buff *skb;
int i;
if (!ipc_mux->initialized) if (!ipc_mux->initialized)
return; return;
@ -479,5 +480,10 @@ void ipc_mux_deinit(struct iosm_mux *ipc_mux)
ipc_mux->channel->dl_pipe.is_open = false; ipc_mux->channel->dl_pipe.is_open = false;
} }
if (ipc_mux->protocol != MUX_LITE) {
for (i = 0; i < IPC_MEM_MUX_IP_SESSION_ENTRIES; i++)
kfree(ipc_mux->ul_adb.pp_qlt[i]);
}
kfree(ipc_mux); kfree(ipc_mux);
} }

View File

@ -5323,7 +5323,8 @@ netdev_features_t netdev_increment_features(netdev_features_t all,
static inline netdev_features_t netdev_add_tso_features(netdev_features_t features, static inline netdev_features_t netdev_add_tso_features(netdev_features_t features,
netdev_features_t mask) netdev_features_t mask)
{ {
return netdev_increment_features(features, NETIF_F_ALL_TSO, mask); return netdev_increment_features(features, NETIF_F_ALL_TSO |
NETIF_F_ALL_FOR_ALL, mask);
} }
int __netdev_update_features(struct net_device *dev); int __netdev_update_features(struct net_device *dev);

View File

@ -71,12 +71,12 @@ static inline void airoha_ppe_dev_check_skb(struct airoha_ppe_dev *dev,
#define NPU_RX1_DESC_NUM 512 #define NPU_RX1_DESC_NUM 512
/* CTRL */ /* CTRL */
#define NPU_RX_DMA_DESC_LAST_MASK BIT(29) #define NPU_RX_DMA_DESC_LAST_MASK BIT(27)
#define NPU_RX_DMA_DESC_LEN_MASK GENMASK(28, 15) #define NPU_RX_DMA_DESC_LEN_MASK GENMASK(26, 14)
#define NPU_RX_DMA_DESC_CUR_LEN_MASK GENMASK(14, 1) #define NPU_RX_DMA_DESC_CUR_LEN_MASK GENMASK(13, 1)
#define NPU_RX_DMA_DESC_DONE_MASK BIT(0) #define NPU_RX_DMA_DESC_DONE_MASK BIT(0)
/* INFO */ /* INFO */
#define NPU_RX_DMA_PKT_COUNT_MASK GENMASK(31, 28) #define NPU_RX_DMA_PKT_COUNT_MASK GENMASK(31, 29)
#define NPU_RX_DMA_PKT_ID_MASK GENMASK(28, 26) #define NPU_RX_DMA_PKT_ID_MASK GENMASK(28, 26)
#define NPU_RX_DMA_SRC_PORT_MASK GENMASK(25, 21) #define NPU_RX_DMA_SRC_PORT_MASK GENMASK(25, 21)
#define NPU_RX_DMA_CRSN_MASK GENMASK(20, 16) #define NPU_RX_DMA_CRSN_MASK GENMASK(20, 16)

View File

@ -189,7 +189,6 @@ int br_handle_egress_vlan_tunnel(struct sk_buff *skb,
IP_TUNNEL_DECLARE_FLAGS(flags) = { }; IP_TUNNEL_DECLARE_FLAGS(flags) = { };
struct metadata_dst *tunnel_dst; struct metadata_dst *tunnel_dst;
__be64 tunnel_id; __be64 tunnel_id;
int err;
if (!vlan) if (!vlan)
return 0; return 0;
@ -199,9 +198,13 @@ int br_handle_egress_vlan_tunnel(struct sk_buff *skb,
return 0; return 0;
skb_dst_drop(skb); skb_dst_drop(skb);
err = skb_vlan_pop(skb); /* For 802.1ad (QinQ), skb_vlan_pop() incorrectly moves the C-VLAN
if (err) * from payload to hwaccel after clearing S-VLAN. We only need to
return err; * clear the hwaccel S-VLAN; the C-VLAN must stay in payload for
* correct VXLAN encapsulation. This is also correct for 802.1Q
* where no C-VLAN exists in payload.
*/
__vlan_hwaccel_clear_tag(skb);
if (BR_INPUT_SKB_CB(skb)->backup_nhid) { if (BR_INPUT_SKB_CB(skb)->backup_nhid) {
__set_bit(IP_TUNNEL_KEY_BIT, flags); __set_bit(IP_TUNNEL_KEY_BIT, flags);

View File

@ -1299,7 +1299,7 @@ int ebt_register_template(const struct ebt_table *t, int (*table_init)(struct ne
list_for_each_entry(tmpl, &template_tables, list) { list_for_each_entry(tmpl, &template_tables, list) {
if (WARN_ON_ONCE(strcmp(t->name, tmpl->name) == 0)) { if (WARN_ON_ONCE(strcmp(t->name, tmpl->name) == 0)) {
mutex_unlock(&ebt_mutex); mutex_unlock(&ebt_mutex);
return -EEXIST; return -EBUSY;
} }
} }

View File

@ -4636,12 +4636,14 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
{ {
struct sk_buff *list_skb = skb_shinfo(skb)->frag_list; struct sk_buff *list_skb = skb_shinfo(skb)->frag_list;
unsigned int tnl_hlen = skb_tnl_header_len(skb); unsigned int tnl_hlen = skb_tnl_header_len(skb);
unsigned int delta_truesize = 0;
unsigned int delta_len = 0; unsigned int delta_len = 0;
struct sk_buff *tail = NULL; struct sk_buff *tail = NULL;
struct sk_buff *nskb, *tmp; struct sk_buff *nskb, *tmp;
int len_diff, err; int len_diff, err;
/* Only skb_gro_receive_list generated skbs arrive here */
DEBUG_NET_WARN_ON_ONCE(!(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST));
skb_push(skb, -skb_network_offset(skb) + offset); skb_push(skb, -skb_network_offset(skb) + offset);
/* Ensure the head is writeable before touching the shared info */ /* Ensure the head is writeable before touching the shared info */
@ -4655,8 +4657,9 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
nskb = list_skb; nskb = list_skb;
list_skb = list_skb->next; list_skb = list_skb->next;
DEBUG_NET_WARN_ON_ONCE(nskb->sk);
err = 0; err = 0;
delta_truesize += nskb->truesize;
if (skb_shared(nskb)) { if (skb_shared(nskb)) {
tmp = skb_clone(nskb, GFP_ATOMIC); tmp = skb_clone(nskb, GFP_ATOMIC);
if (tmp) { if (tmp) {
@ -4699,7 +4702,6 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
goto err_linearize; goto err_linearize;
} }
skb->truesize = skb->truesize - delta_truesize;
skb->data_len = skb->data_len - delta_len; skb->data_len = skb->data_len - delta_len;
skb->len = skb->len - delta_len; skb->len = skb->len - delta_len;

View File

@ -3896,7 +3896,7 @@ void sock_enable_timestamp(struct sock *sk, enum sock_flags flag)
int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len, int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
int level, int type) int level, int type)
{ {
struct sock_exterr_skb *serr; struct sock_extended_err ee;
struct sk_buff *skb; struct sk_buff *skb;
int copied, err; int copied, err;
@ -3916,8 +3916,9 @@ int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
sock_recv_timestamp(msg, sk, skb); sock_recv_timestamp(msg, sk, skb);
serr = SKB_EXT_ERR(skb); /* We must use a bounce buffer for CONFIG_HARDENED_USERCOPY=y */
put_cmsg(msg, level, type, sizeof(serr->ee), &serr->ee); ee = SKB_EXT_ERR(skb)->ee;
put_cmsg(msg, level, type, sizeof(ee), &ee);
msg->msg_flags |= MSG_ERRQUEUE; msg->msg_flags |= MSG_ERRQUEUE;
err = copied; err = copied;

View File

@ -564,7 +564,7 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
skb_reserve(skb, hlen); skb_reserve(skb, hlen);
skb_reset_network_header(skb); skb_reset_network_header(skb);
arp = skb_put(skb, arp_hdr_len(dev)); skb_put(skb, arp_hdr_len(dev));
skb->dev = dev; skb->dev = dev;
skb->protocol = htons(ETH_P_ARP); skb->protocol = htons(ETH_P_ARP);
if (!src_hw) if (!src_hw)
@ -572,12 +572,13 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
if (!dest_hw) if (!dest_hw)
dest_hw = dev->broadcast; dest_hw = dev->broadcast;
/* /* Fill the device header for the ARP frame.
* Fill the device header for the ARP frame * Note: skb->head can be changed.
*/ */
if (dev_hard_header(skb, dev, ptype, dest_hw, src_hw, skb->len) < 0) if (dev_hard_header(skb, dev, ptype, dest_hw, src_hw, skb->len) < 0)
goto out; goto out;
arp = arp_hdr(skb);
/* /*
* Fill out the arp protocol part. * Fill out the arp protocol part.
* *

View File

@ -488,6 +488,8 @@ int inet_frag_queue_insert(struct inet_frag_queue *q, struct sk_buff *skb,
} }
FRAG_CB(skb)->ip_defrag_offset = offset; FRAG_CB(skb)->ip_defrag_offset = offset;
if (offset)
nf_reset_ct(skb);
return IPFRAG_OK; return IPFRAG_OK;
} }

View File

@ -828,10 +828,8 @@ out:
out_free: out_free:
if (free) if (free)
kfree(ipc.opt); kfree(ipc.opt);
if (!err) { if (!err)
icmp_out_count(sock_net(sk), user_icmph.type);
return len; return len;
}
return err; return err;
do_confirm: do_confirm:

View File

@ -2652,10 +2652,8 @@ static int tcp_recvmsg_locked(struct sock *sk, struct msghdr *msg, size_t len,
if (sk->sk_state == TCP_LISTEN) if (sk->sk_state == TCP_LISTEN)
goto out; goto out;
if (tp->recvmsg_inq) { if (tp->recvmsg_inq)
*cmsg_flags = TCP_CMSG_INQ; *cmsg_flags = TCP_CMSG_INQ;
msg->msg_get_inq = 1;
}
timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
/* Urgent data needs to be handled specially. */ /* Urgent data needs to be handled specially. */
@ -2929,10 +2927,10 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,
ret = tcp_recvmsg_locked(sk, msg, len, flags, &tss, &cmsg_flags); ret = tcp_recvmsg_locked(sk, msg, len, flags, &tss, &cmsg_flags);
release_sock(sk); release_sock(sk);
if ((cmsg_flags || msg->msg_get_inq) && ret >= 0) { if ((cmsg_flags | msg->msg_get_inq) && ret >= 0) {
if (cmsg_flags & TCP_CMSG_TS) if (cmsg_flags & TCP_CMSG_TS)
tcp_recv_timestamp(msg, sk, &tss); tcp_recv_timestamp(msg, sk, &tss);
if (msg->msg_get_inq) { if ((cmsg_flags & TCP_CMSG_INQ) | msg->msg_get_inq) {
msg->msg_inq = tcp_inq_hint(sk); msg->msg_inq = tcp_inq_hint(sk);
if (cmsg_flags & TCP_CMSG_INQ) if (cmsg_flags & TCP_CMSG_INQ)
put_cmsg(msg, SOL_TCP, TCP_CM_INQ, put_cmsg(msg, SOL_TCP, TCP_CM_INQ,

View File

@ -1851,6 +1851,7 @@ void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len)
sk_peek_offset_bwd(sk, len); sk_peek_offset_bwd(sk, len);
if (!skb_shared(skb)) { if (!skb_shared(skb)) {
skb_orphan(skb);
skb_attempt_defer_free(skb); skb_attempt_defer_free(skb);
return; return;
} }

View File

@ -90,6 +90,9 @@ next_interface:
/* next (or first) interface */ /* next (or first) interface */
iter->sdata = list_prepare_entry(iter->sdata, &local->interfaces, list); iter->sdata = list_prepare_entry(iter->sdata, &local->interfaces, list);
list_for_each_entry_continue(iter->sdata, &local->interfaces, list) { list_for_each_entry_continue(iter->sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(iter->sdata))
continue;
/* AP_VLAN has a chanctx pointer but follows AP */ /* AP_VLAN has a chanctx pointer but follows AP */
if (iter->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) if (iter->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
continue; continue;

View File

@ -1533,6 +1533,10 @@ static void __sta_info_destroy_part2(struct sta_info *sta, bool recalc)
} }
} }
sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
if (sinfo)
sta_set_sinfo(sta, sinfo, true);
if (sta->uploaded) { if (sta->uploaded) {
ret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE, ret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE,
IEEE80211_STA_NOTEXIST); IEEE80211_STA_NOTEXIST);
@ -1541,9 +1545,6 @@ static void __sta_info_destroy_part2(struct sta_info *sta, bool recalc)
sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr); sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr);
sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
if (sinfo)
sta_set_sinfo(sta, sinfo, true);
cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL); cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL);
kfree(sinfo); kfree(sinfo);

View File

@ -2397,6 +2397,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
if (chanctx_conf) if (chanctx_conf)
chandef = &chanctx_conf->def; chandef = &chanctx_conf->def;
else if (local->emulate_chanctx)
chandef = &local->hw.conf.chandef;
else else
goto fail_rcu; goto fail_rcu;

View File

@ -229,6 +229,7 @@ static int __nf_conncount_add(struct net *net,
nf_ct_put(found_ct); nf_ct_put(found_ct);
} }
list->last_gc = (u32)jiffies;
add_new_node: add_new_node:
if (WARN_ON_ONCE(list->count > INT_MAX)) { if (WARN_ON_ONCE(list->count > INT_MAX)) {
@ -248,7 +249,6 @@ add_new_node:
conn->jiffies32 = (u32)jiffies; conn->jiffies32 = (u32)jiffies;
list_add_tail(&conn->node, &list->head); list_add_tail(&conn->node, &list->head);
list->count++; list->count++;
list->last_gc = (u32)jiffies;
out_put: out_put:
if (refcounted) if (refcounted)

View File

@ -89,7 +89,7 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger)
if (pf == NFPROTO_UNSPEC) { if (pf == NFPROTO_UNSPEC) {
for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) {
if (rcu_access_pointer(loggers[i][logger->type])) { if (rcu_access_pointer(loggers[i][logger->type])) {
ret = -EEXIST; ret = -EBUSY;
goto unlock; goto unlock;
} }
} }
@ -97,7 +97,7 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger)
rcu_assign_pointer(loggers[i][logger->type], logger); rcu_assign_pointer(loggers[i][logger->type], logger);
} else { } else {
if (rcu_access_pointer(loggers[pf][logger->type])) { if (rcu_access_pointer(loggers[pf][logger->type])) {
ret = -EEXIST; ret = -EBUSY;
goto unlock; goto unlock;
} }
rcu_assign_pointer(loggers[pf][logger->type], logger); rcu_assign_pointer(loggers[pf][logger->type], logger);

View File

@ -4439,7 +4439,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
if (!nft_use_inc(&chain->use)) { if (!nft_use_inc(&chain->use)) {
err = -EMFILE; err = -EMFILE;
goto err_release_rule; goto err_destroy_flow;
} }
if (info->nlh->nlmsg_flags & NLM_F_REPLACE) { if (info->nlh->nlmsg_flags & NLM_F_REPLACE) {
@ -4489,6 +4489,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
err_destroy_flow_rule: err_destroy_flow_rule:
nft_use_dec_restore(&chain->use); nft_use_dec_restore(&chain->use);
err_destroy_flow:
if (flow) if (flow)
nft_flow_rule_destroy(flow); nft_flow_rule_destroy(flow);
err_release_rule: err_release_rule:

View File

@ -1317,8 +1317,8 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
else else
dup_end = dup_key; dup_end = dup_key;
if (!memcmp(start, dup_key->data, sizeof(*dup_key->data)) && if (!memcmp(start, dup_key->data, set->klen) &&
!memcmp(end, dup_end->data, sizeof(*dup_end->data))) { !memcmp(end, dup_end->data, set->klen)) {
*elem_priv = &dup->priv; *elem_priv = &dup->priv;
return -EEXIST; return -EEXIST;
} }

View File

@ -48,7 +48,7 @@ static void nft_synproxy_eval_v4(const struct nft_synproxy *priv,
struct tcphdr *_tcph, struct tcphdr *_tcph,
struct synproxy_options *opts) struct synproxy_options *opts)
{ {
struct nf_synproxy_info info = priv->info; struct nf_synproxy_info info = READ_ONCE(priv->info);
struct net *net = nft_net(pkt); struct net *net = nft_net(pkt);
struct synproxy_net *snet = synproxy_pernet(net); struct synproxy_net *snet = synproxy_pernet(net);
struct sk_buff *skb = pkt->skb; struct sk_buff *skb = pkt->skb;
@ -79,7 +79,7 @@ static void nft_synproxy_eval_v6(const struct nft_synproxy *priv,
struct tcphdr *_tcph, struct tcphdr *_tcph,
struct synproxy_options *opts) struct synproxy_options *opts)
{ {
struct nf_synproxy_info info = priv->info; struct nf_synproxy_info info = READ_ONCE(priv->info);
struct net *net = nft_net(pkt); struct net *net = nft_net(pkt);
struct synproxy_net *snet = synproxy_pernet(net); struct synproxy_net *snet = synproxy_pernet(net);
struct sk_buff *skb = pkt->skb; struct sk_buff *skb = pkt->skb;
@ -340,7 +340,7 @@ static void nft_synproxy_obj_update(struct nft_object *obj,
struct nft_synproxy *newpriv = nft_obj_data(newobj); struct nft_synproxy *newpriv = nft_obj_data(newobj);
struct nft_synproxy *priv = nft_obj_data(obj); struct nft_synproxy *priv = nft_obj_data(obj);
priv->info = newpriv->info; WRITE_ONCE(priv->info, newpriv->info);
} }
static struct nft_object_type nft_synproxy_obj_type; static struct nft_object_type nft_synproxy_obj_type;

View File

@ -1764,7 +1764,7 @@ EXPORT_SYMBOL_GPL(xt_hook_ops_alloc);
int xt_register_template(const struct xt_table *table, int xt_register_template(const struct xt_table *table,
int (*table_init)(struct net *net)) int (*table_init)(struct net *net))
{ {
int ret = -EEXIST, af = table->af; int ret = -EBUSY, af = table->af;
struct xt_template *t; struct xt_template *t;
mutex_lock(&xt[af].mutex); mutex_lock(&xt[af].mutex);

View File

@ -940,6 +940,8 @@ void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
int ret; int ret;
idr_for_each_entry_ul(idr, p, tmp, id) { idr_for_each_entry_ul(idr, p, tmp, id) {
if (IS_ERR(p))
continue;
if (tc_act_in_hw(p) && !mutex_taken) { if (tc_act_in_hw(p) && !mutex_taken) {
rtnl_lock(); rtnl_lock();
mutex_taken = true; mutex_taken = true;

View File

@ -266,21 +266,9 @@ static int tcf_mirred_to_dev(struct sk_buff *skb, struct tcf_mirred *m,
goto err_cant_do; goto err_cant_do;
} }
/* we could easily avoid the clone only if called by ingress and clsact;
* since we can't easily detect the clsact caller, skip clone only for
* ingress - that covers the TC S/W datapath.
*/
at_ingress = skb_at_tc_ingress(skb);
dont_clone = skb_at_tc_ingress(skb) && is_redirect &&
tcf_mirred_can_reinsert(retval);
if (!dont_clone) {
skb_to_send = skb_clone(skb, GFP_ATOMIC);
if (!skb_to_send)
goto err_cant_do;
}
want_ingress = tcf_mirred_act_wants_ingress(m_eaction); want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
at_ingress = skb_at_tc_ingress(skb);
if (dev == skb->dev && want_ingress == at_ingress) { if (dev == skb->dev && want_ingress == at_ingress) {
pr_notice_once("tc mirred: Loop (%s:%s --> %s:%s)\n", pr_notice_once("tc mirred: Loop (%s:%s --> %s:%s)\n",
netdev_name(skb->dev), netdev_name(skb->dev),
@ -290,6 +278,18 @@ static int tcf_mirred_to_dev(struct sk_buff *skb, struct tcf_mirred *m,
goto err_cant_do; goto err_cant_do;
} }
/* we could easily avoid the clone only if called by ingress and clsact;
* since we can't easily detect the clsact caller, skip clone only for
* ingress - that covers the TC S/W datapath.
*/
dont_clone = skb_at_tc_ingress(skb) && is_redirect &&
tcf_mirred_can_reinsert(retval);
if (!dont_clone) {
skb_to_send = skb_clone(skb, GFP_ATOMIC);
if (!skb_to_send)
goto err_cant_do;
}
/* All mirred/redirected skbs should clear previous ct info */ /* All mirred/redirected skbs should clear previous ct info */
nf_reset_ct(skb_to_send); nf_reset_ct(skb_to_send);
if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */ if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */

View File

@ -1481,7 +1481,7 @@ static void qfq_reset_qdisc(struct Qdisc *sch)
for (i = 0; i < q->clhash.hashsize; i++) { for (i = 0; i < q->clhash.hashsize; i++) {
hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) { hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) {
if (cl->qdisc->q.qlen > 0) if (cl_is_active(cl))
qfq_deactivate_class(q, cl); qfq_deactivate_class(q, cl);
qdisc_reset(cl->qdisc); qdisc_reset(cl->qdisc);

View File

@ -2904,7 +2904,6 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
unsigned int last_len; unsigned int last_len;
struct unix_sock *u; struct unix_sock *u;
int copied = 0; int copied = 0;
bool do_cmsg;
int err = 0; int err = 0;
long timeo; long timeo;
int target; int target;
@ -2930,9 +2929,6 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
u = unix_sk(sk); u = unix_sk(sk);
do_cmsg = READ_ONCE(u->recvmsg_inq);
if (do_cmsg)
msg->msg_get_inq = 1;
redo: redo:
/* Lock the socket to prevent queue disordering /* Lock the socket to prevent queue disordering
* while sleeps in memcpy_tomsg * while sleeps in memcpy_tomsg
@ -3090,9 +3086,11 @@ unlock:
mutex_unlock(&u->iolock); mutex_unlock(&u->iolock);
if (msg) { if (msg) {
bool do_cmsg = READ_ONCE(u->recvmsg_inq);
scm_recv_unix(sock, msg, &scm, flags); scm_recv_unix(sock, msg, &scm, flags);
if (msg->msg_get_inq && (copied ?: err) >= 0) { if ((do_cmsg | msg->msg_get_inq) && (copied ?: err) >= 0) {
msg->msg_inq = READ_ONCE(u->inq_len); msg->msg_inq = READ_ONCE(u->inq_len);
if (do_cmsg) if (do_cmsg)
put_cmsg(msg, SOL_SOCKET, SCM_INQ, put_cmsg(msg, SOL_SOCKET, SCM_INQ,

View File

@ -1787,6 +1787,10 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
} else { } else {
newsock->state = SS_CONNECTED; newsock->state = SS_CONNECTED;
sock_graft(connected, newsock); sock_graft(connected, newsock);
set_bit(SOCK_CUSTOM_SOCKOPT,
&connected->sk_socket->flags);
if (vsock_msgzerocopy_allow(vconnected->transport)) if (vsock_msgzerocopy_allow(vconnected->transport))
set_bit(SOCK_SUPPORT_ZC, set_bit(SOCK_SUPPORT_ZC,
&connected->sk_socket->flags); &connected->sk_socket->flags);

View File

@ -1101,6 +1101,10 @@ static int compat_standard_call(struct net_device *dev,
return ioctl_standard_call(dev, iwr, cmd, info, handler); return ioctl_standard_call(dev, iwr, cmd, info, handler);
iwp_compat = (struct compat_iw_point *) &iwr->u.data; iwp_compat = (struct compat_iw_point *) &iwr->u.data;
/* struct iw_point has a 32bit hole on 64bit arches. */
memset(&iwp, 0, sizeof(iwp));
iwp.pointer = compat_ptr(iwp_compat->pointer); iwp.pointer = compat_ptr(iwp_compat->pointer);
iwp.length = iwp_compat->length; iwp.length = iwp_compat->length;
iwp.flags = iwp_compat->flags; iwp.flags = iwp_compat->flags;

View File

@ -228,6 +228,10 @@ int compat_private_call(struct net_device *dev, struct iwreq *iwr,
struct iw_point iwp; struct iw_point iwp;
iwp_compat = (struct compat_iw_point *) &iwr->u.data; iwp_compat = (struct compat_iw_point *) &iwr->u.data;
/* struct iw_point has a 32bit hole on 64bit arches. */
memset(&iwp, 0, sizeof(iwp));
iwp.pointer = compat_ptr(iwp_compat->pointer); iwp.pointer = compat_ptr(iwp_compat->pointer);
iwp.length = iwp_compat->length; iwp.length = iwp_compat->length;
iwp.flags = iwp_compat->flags; iwp.flags = iwp_compat->flags;

View File

@ -51,7 +51,6 @@ install: libynl.a lib/*.h
@echo -e "\tINSTALL pyynl" @echo -e "\tINSTALL pyynl"
@pip install --prefix=$(DESTDIR)$(prefix) . @pip install --prefix=$(DESTDIR)$(prefix) .
@make -C generated install @make -C generated install
@make -C tests install
run_tests: run_tests:
@$(MAKE) -C tests run_tests @$(MAKE) -C tests run_tests

View File

@ -22,7 +22,7 @@ try:
NlError, RtnlFamily, DevlinkFamily, PSPFamily NlError, RtnlFamily, DevlinkFamily, PSPFamily
from net.lib.py import CmdExitFailure from net.lib.py import CmdExitFailure
from net.lib.py import bkg, cmd, bpftool, bpftrace, defer, ethtool, \ from net.lib.py import bkg, cmd, bpftool, bpftrace, defer, ethtool, \
fd_read_timeout, ip, rand_port, wait_port_listen, wait_file fd_read_timeout, ip, rand_port, wait_port_listen, wait_file, tool
from net.lib.py import KsftSkipEx, KsftFailEx, KsftXfailEx from net.lib.py import KsftSkipEx, KsftFailEx, KsftXfailEx
from net.lib.py import ksft_disruptive, ksft_exit, ksft_pr, ksft_run, \ from net.lib.py import ksft_disruptive, ksft_exit, ksft_pr, ksft_run, \
ksft_setup, ksft_variants, KsftNamedVariant ksft_setup, ksft_variants, KsftNamedVariant
@ -37,7 +37,7 @@ try:
"CmdExitFailure", "CmdExitFailure",
"bkg", "cmd", "bpftool", "bpftrace", "defer", "ethtool", "bkg", "cmd", "bpftool", "bpftrace", "defer", "ethtool",
"fd_read_timeout", "ip", "rand_port", "fd_read_timeout", "ip", "rand_port",
"wait_port_listen", "wait_file", "wait_port_listen", "wait_file", "tool",
"KsftSkipEx", "KsftFailEx", "KsftXfailEx", "KsftSkipEx", "KsftFailEx", "KsftXfailEx",
"ksft_disruptive", "ksft_exit", "ksft_pr", "ksft_run", "ksft_disruptive", "ksft_exit", "ksft_pr", "ksft_run",
"ksft_setup", "ksft_variants", "KsftNamedVariant", "ksft_setup", "ksft_variants", "KsftNamedVariant",

View File

@ -52,6 +52,39 @@ cleanup_ns()
ip netns del nssv ip netns del nssv
} }
is_carrier_up()
{
local netns="$1"
local nsim_dev="$2"
test "$(ip netns exec "$netns" \
cat /sys/class/net/"$nsim_dev"/carrier 2>/dev/null)" -eq 1
}
assert_carrier_up()
{
local netns="$1"
local nsim_dev="$2"
if ! is_carrier_up "$netns" "$nsim_dev"; then
echo "$nsim_dev's carrier should be UP, but it isn't"
cleanup_ns
exit 1
fi
}
assert_carrier_down()
{
local netns="$1"
local nsim_dev="$2"
if is_carrier_up "$netns" "$nsim_dev"; then
echo "$nsim_dev's carrier should be DOWN, but it isn't"
cleanup_ns
exit 1
fi
}
### ###
### Code start ### Code start
### ###
@ -113,6 +146,32 @@ if [ $? -eq 0 ]; then
exit 1 exit 1
fi fi
# netdevsim carrier state consistency checking
assert_carrier_up nssv "$NSIM_DEV_1_NAME"
assert_carrier_up nscl "$NSIM_DEV_2_NAME"
echo "$NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX" > "$NSIM_DEV_SYS_UNLINK"
assert_carrier_down nssv "$NSIM_DEV_1_NAME"
assert_carrier_down nscl "$NSIM_DEV_2_NAME"
ip netns exec nssv ip link set dev "$NSIM_DEV_1_NAME" down
ip netns exec nssv ip link set dev "$NSIM_DEV_1_NAME" up
assert_carrier_down nssv "$NSIM_DEV_1_NAME"
assert_carrier_down nscl "$NSIM_DEV_2_NAME"
echo "$NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX $NSIM_DEV_2_FD:$NSIM_DEV_2_IFIDX" > $NSIM_DEV_SYS_LINK
assert_carrier_up nssv "$NSIM_DEV_1_NAME"
assert_carrier_up nscl "$NSIM_DEV_2_NAME"
ip netns exec nssv ip link set dev "$NSIM_DEV_1_NAME" down
ip netns exec nssv ip link set dev "$NSIM_DEV_1_NAME" up
assert_carrier_up nssv "$NSIM_DEV_1_NAME"
assert_carrier_up nscl "$NSIM_DEV_2_NAME"
# send/recv packets # send/recv packets
tmp_file=$(mktemp) tmp_file=$(mktemp)

View File

@ -13,7 +13,7 @@ from .ksft import KsftFailEx, KsftSkipEx, KsftXfailEx, ksft_pr, ksft_eq, \
from .netns import NetNS, NetNSEnter from .netns import NetNS, NetNSEnter
from .nsim import NetdevSim, NetdevSimDev from .nsim import NetdevSim, NetdevSimDev
from .utils import CmdExitFailure, fd_read_timeout, cmd, bkg, defer, \ from .utils import CmdExitFailure, fd_read_timeout, cmd, bkg, defer, \
bpftool, ip, ethtool, bpftrace, rand_port, wait_port_listen, wait_file bpftool, ip, ethtool, bpftrace, rand_port, wait_port_listen, wait_file, tool
from .ynl import NlError, YnlFamily, EthtoolFamily, NetdevFamily, RtnlFamily, RtnlAddrFamily from .ynl import NlError, YnlFamily, EthtoolFamily, NetdevFamily, RtnlFamily, RtnlAddrFamily
from .ynl import NetshaperFamily, DevlinkFamily, PSPFamily from .ynl import NetshaperFamily, DevlinkFamily, PSPFamily
@ -26,7 +26,7 @@ __all__ = ["KSRC",
"NetNS", "NetNSEnter", "NetNS", "NetNSEnter",
"CmdExitFailure", "fd_read_timeout", "cmd", "bkg", "defer", "CmdExitFailure", "fd_read_timeout", "cmd", "bkg", "defer",
"bpftool", "ip", "ethtool", "bpftrace", "rand_port", "bpftool", "ip", "ethtool", "bpftrace", "rand_port",
"wait_port_listen", "wait_file", "wait_port_listen", "wait_file", "tool",
"NetdevSim", "NetdevSimDev", "NetdevSim", "NetdevSimDev",
"NetshaperFamily", "DevlinkFamily", "PSPFamily", "NlError", "NetshaperFamily", "DevlinkFamily", "PSPFamily", "NlError",
"YnlFamily", "EthtoolFamily", "NetdevFamily", "RtnlFamily", "YnlFamily", "EthtoolFamily", "NetdevFamily", "RtnlFamily",

View File

@ -3,6 +3,7 @@
top_srcdir = ../../../../.. top_srcdir = ../../../../..
CFLAGS += -Wall -Wl,--no-as-needed -O2 -g -I$(top_srcdir)/usr/include $(KHDR_INCLUDES) CFLAGS += -Wall -Wl,--no-as-needed -O2 -g -I$(top_srcdir)/usr/include $(KHDR_INCLUDES)
CFLAGS += -I$(top_srcdir)/tools/include
TEST_PROGS := \ TEST_PROGS := \
diag.sh \ diag.sh \

View File

@ -33,6 +33,7 @@
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/time_types.h> #include <linux/time_types.h>
#include <linux/sockios.h> #include <linux/sockios.h>
#include <linux/compiler.h>
extern int optind; extern int optind;
@ -140,7 +141,7 @@ static void die_usage(void)
exit(1); exit(1);
} }
static void xerror(const char *fmt, ...) static void __noreturn xerror(const char *fmt, ...)
{ {
va_list ap; va_list ap;

View File

@ -5,6 +5,7 @@
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/inet_diag.h> #include <linux/inet_diag.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/compiler.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <linux/tcp.h> #include <linux/tcp.h>
@ -87,7 +88,7 @@ enum {
#define rta_getattr(type, value) (*(type *)RTA_DATA(value)) #define rta_getattr(type, value) (*(type *)RTA_DATA(value))
static void die_perror(const char *msg) static void __noreturn die_perror(const char *msg)
{ {
perror(msg); perror(msg);
exit(1); exit(1);

View File

@ -28,6 +28,7 @@
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/sockios.h> #include <linux/sockios.h>
#include <linux/compiler.h>
#ifndef IPPROTO_MPTCP #ifndef IPPROTO_MPTCP
#define IPPROTO_MPTCP 262 #define IPPROTO_MPTCP 262
@ -40,7 +41,7 @@ static int pf = AF_INET;
static int proto_tx = IPPROTO_MPTCP; static int proto_tx = IPPROTO_MPTCP;
static int proto_rx = IPPROTO_MPTCP; static int proto_rx = IPPROTO_MPTCP;
static void die_perror(const char *msg) static void __noreturn die_perror(const char *msg)
{ {
perror(msg); perror(msg);
exit(1); exit(1);
@ -52,7 +53,7 @@ static void die_usage(int r)
exit(r); exit(r);
} }
static void xerror(const char *fmt, ...) static void __noreturn xerror(const char *fmt, ...)
{ {
va_list ap; va_list ap;

View File

@ -25,6 +25,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/compiler.h>
static int pf = AF_INET; static int pf = AF_INET;
@ -127,7 +128,7 @@ struct so_state {
#define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif #endif
static void die_perror(const char *msg) static void __noreturn die_perror(const char *msg)
{ {
perror(msg); perror(msg);
exit(1); exit(1);
@ -139,7 +140,7 @@ static void die_usage(int r)
exit(r); exit(r);
} }
static void xerror(const char *fmt, ...) static void __noreturn xerror(const char *fmt, ...)
{ {
va_list ap; va_list ap;

View File

@ -29,7 +29,7 @@ TYPES="net_port port_net net6_port port_proto net6_port_mac net6_port_mac_proto
net6_port_net6_port net_port_mac_proto_net" net6_port_net6_port net_port_mac_proto_net"
# Reported bugs, also described by TYPE_ variables below # Reported bugs, also described by TYPE_ variables below
BUGS="flush_remove_add reload net_port_proto_match avx2_mismatch doublecreate" BUGS="flush_remove_add reload net_port_proto_match avx2_mismatch doublecreate insert_overlap"
# List of possible paths to pktgen script from kernel tree for performance tests # List of possible paths to pktgen script from kernel tree for performance tests
PKTGEN_SCRIPT_PATHS=" PKTGEN_SCRIPT_PATHS="
@ -420,6 +420,18 @@ race_repeat 0
perf_duration 0 perf_duration 0
" "
TYPE_insert_overlap="
display reject overlapping range on add
type_spec ipv4_addr . ipv4_addr
chain_spec ip saddr . ip daddr
dst addr4
proto icmp
race_repeat 0
perf_duration 0
"
# Set template for all tests, types and rules are filled in depending on test # Set template for all tests, types and rules are filled in depending on test
set_template=' set_template='
flush ruleset flush ruleset
@ -1954,6 +1966,37 @@ EOF
return 0 return 0
} }
add_fail()
{
if nft add element inet filter test "$1" 2>/dev/null ; then
err "Returned success for add ${1} given set:"
err "$(nft -a list set inet filter test )"
return 1
fi
return 0
}
test_bug_insert_overlap()
{
local elements="1.2.3.4 . 1.2.4.1"
setup veth send_"${proto}" set || return ${ksft_skip}
add "{ $elements }" || return 1
elements="1.2.3.0-1.2.3.4 . 1.2.4.1"
add_fail "{ $elements }" || return 1
elements="1.2.3.0-1.2.3.4 . 1.2.4.2"
add "{ $elements }" || return 1
elements="1.2.3.4 . 1.2.4.1-1.2.4.2"
add_fail "{ $elements }" || return 1
return 0
}
test_reported_issues() { test_reported_issues() {
eval test_bug_"${subtest}" eval test_bug_"${subtest}"
} }

View File

@ -1098,5 +1098,52 @@
"teardown": [ "teardown": [
"$TC qdisc del dev $DUMMY root" "$TC qdisc del dev $DUMMY root"
] ]
},
{
"id": "4ed9",
"name": "Try to redirect to self on egress with clsact",
"category": [
"filter",
"mirred"
],
"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 clsact",
"$TC filter add dev $DUMMY egress protocol ip prio 10 matchall action mirred egress redirect dev $DUMMY index 1"
],
"cmdUnderTest": "ping -c1 -W0.01 -I $DUMMY 10.10.10.1",
"expExitCode": "1",
"verifyCmd": "$TC -j -s actions get action mirred index 1",
"matchJSON": [
{
"total acts": 0
},
{
"actions": [
{
"order": 1,
"kind": "mirred",
"mirred_action": "redirect",
"direction": "egress",
"index": 1,
"stats": {
"packets": 1,
"overlimits": 1
},
"not_in_hw": true
}
]
}
],
"teardown": [
"$TC qdisc del dev $DUMMY clsact"
]
} }
] ]

View File

@ -2192,6 +2192,33 @@ static void test_stream_nolinger_server(const struct test_opts *opts)
close(fd); close(fd);
} }
static void test_stream_accepted_setsockopt_client(const struct test_opts *opts)
{
int fd;
fd = vsock_stream_connect(opts->peer_cid, opts->peer_port);
if (fd < 0) {
perror("connect");
exit(EXIT_FAILURE);
}
close(fd);
}
static void test_stream_accepted_setsockopt_server(const struct test_opts *opts)
{
int fd;
fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL);
if (fd < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
enable_so_zerocopy_check(fd);
close(fd);
}
static struct test_case test_cases[] = { static struct test_case test_cases[] = {
{ {
.name = "SOCK_STREAM connection reset", .name = "SOCK_STREAM connection reset",
@ -2371,6 +2398,11 @@ static struct test_case test_cases[] = {
.run_client = test_seqpacket_unread_bytes_client, .run_client = test_seqpacket_unread_bytes_client,
.run_server = test_seqpacket_unread_bytes_server, .run_server = test_seqpacket_unread_bytes_server,
}, },
{
.name = "SOCK_STREAM accept()ed socket custom setsockopt()",
.run_client = test_stream_accepted_setsockopt_client,
.run_server = test_stream_accepted_setsockopt_server,
},
{}, {},
}; };