1
0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2026-01-11 00:50:21 +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@solidboot.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>
Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org>
Kalle Valo <kvalo@kernel.org> <quic_kvalo@quicinc.com>

View File

@ -142,7 +142,7 @@ attribute-sets:
name: ifindex
doc: |
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
because they wait for all memory to be returned).
type: u32
@ -601,7 +601,9 @@ operations:
name: page-pool-get
doc: |
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
do:
request:

View File

@ -1283,6 +1283,7 @@ F: include/uapi/drm/amdxdna_accel.h
AMD XGBE DRIVER
M: "Shyam Sundar S K" <Shyam-sundar.S-k@amd.com>
M: Raju Rangoju <Raju.Rangoju@amd.com>
L: netdev@vger.kernel.org
S: Maintained
F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi
@ -18283,7 +18284,7 @@ X: net/wireless/
X: tools/testing/selftests/net/can/
NETWORKING [IOAM]
M: Justin Iurman <justin.iurman@uliege.be>
M: Justin Iurman <justin.iurman@gmail.com>
S: Maintained
F: Documentation/networking/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);
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);
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)
{
struct device_node *phy_handle = NULL;
struct fwnode_handle *ports_fwnode;
struct fwnode_handle *port_fwnode;
struct dsa_switch *ds = chip->ds;
struct mv88e6xxx_port *p;
struct dsa_port *dp;
int tx_amp;
int err;
u16 reg;
u32 val;
@ -3582,23 +3579,6 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
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
* database, and allow bidirectional communication between the
* 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_get_regs_len = mv88e6352_serdes_get_regs_len,
.serdes_get_regs = mv88e6352_serdes_get_regs,
.serdes_set_tx_amplitude = mv88e6352_serdes_set_tx_amplitude,
.gpio_ops = &mv88e6352_gpio_ops,
.phylink_get_caps = mv88e6352_phylink_get_caps,
.pcs_ops = &mv88e6352_pcs_ops,
@ -5044,7 +5023,6 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
.serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
.serdes_get_regs = mv88e6352_serdes_get_regs,
.serdes_set_tx_amplitude = mv88e6352_serdes_set_tx_amplitude,
.gpio_ops = &mv88e6352_gpio_ops,
.avb_ops = &mv88e6352_avb_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_regs_len = mv88e6352_serdes_get_regs_len,
.serdes_get_regs = mv88e6352_serdes_get_regs,
.serdes_set_tx_amplitude = mv88e6352_serdes_set_tx_amplitude,
.phylink_get_caps = mv88e6352_phylink_get_caps,
.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 *_p);
/* SERDES SGMII/Fiber Output Amplitude */
int (*serdes_set_tx_amplitude)(struct mv88e6xxx_chip *chip, int port,
int val);
/* Address Translation Unit operations */
int (*atu_get_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);
}
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,
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;
}
}
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_STATUS 0x13
#define MV88E6352_SERDES_SPEC_CTRL2 0x1a
#define MV88E6352_SERDES_OUT_AMP_MASK 0x0007
#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);
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. */
static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
int port)

View File

@ -1473,7 +1473,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
return 0;
free_ring:
dma_free_coherent(&pdev->dev,
dma_free_coherent(gendev,
sizeof(struct boom_rx_desc) * RX_RING_SIZE +
sizeof(struct boom_tx_desc) * TX_RING_SIZE,
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;
rcu_read_lock();
npu = rcu_dereference(eth->npu);
mutex_lock(&flow_offload_mutex);
npu = rcu_replace_pointer(eth->npu, NULL,
lockdep_is_held(&flow_offload_mutex));
if (npu) {
npu->ops.ppe_deinit(npu);
airoha_npu_put(npu);
}
rcu_read_unlock();
mutex_unlock(&flow_offload_mutex);
rhashtable_destroy(&eth->ppe->l2_flows);
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;
devl_lock(devlink);
value.vbool = false;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
value);
devl_unlock(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;
}
devl_lock(devlink);
value.vbool = ena_phc_is_enabled(adapter);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
value);
devl_unlock(devlink);
return 0;
}

View File

@ -259,6 +259,7 @@ config BNGE
depends on PCI
select NET_DEVLINK
select PAGE_POOL
select AUXILIARY_BUS
help
This driver supports Broadcom ThorUltra 50/100/200/400/800 gigabit
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;
u16 idx = agg_id & MAX_TPA_P5_MASK;
if (test_bit(idx, map->agg_idx_bmap))
idx = find_first_zero_bit(map->agg_idx_bmap,
BNXT_AGG_IDX_BMAP_SIZE);
if (test_bit(idx, map->agg_idx_bmap)) {
idx = find_first_zero_bit(map->agg_idx_bmap, MAX_TPA_P5);
if (idx >= MAX_TPA_P5)
return INVALID_HW_RING_ID;
}
__set_bit(idx, map->agg_idx_bmap);
map->agg_id_tbl[agg_id] = 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) {
agg_id = TPA_START_AGG_ID_P5(tpa_start);
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 {
agg_id = TPA_START_AGG_ID(tpa_start);
}
@ -16882,12 +16891,12 @@ init_err_dl:
init_err_pci_clean:
bnxt_hwrm_func_drv_unrgtr(bp);
bnxt_free_hwrm_resources(bp);
bnxt_hwmon_uninit(bp);
bnxt_ethtool_free(bp);
bnxt_ptp_clear(bp);
kfree(bp->ptp_cfg);
bp->ptp_cfg = NULL;
bnxt_free_hwrm_resources(bp);
bnxt_hwmon_uninit(bp);
bnxt_ethtool_free(bp);
kfree(bp->fw_health);
bp->fw_health = NULL;
bnxt_cleanup_pci(bp);

View File

@ -1080,11 +1080,9 @@ struct bnxt_tpa_info {
struct rx_agg_cmp *agg_arr;
};
#define BNXT_AGG_IDX_BMAP_SIZE (MAX_TPA_P5 / BITS_PER_LONG)
struct bnxt_tpa_idx_map {
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 {

View File

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

View File

@ -284,8 +284,7 @@ struct idpf_port_stats {
struct idpf_fsteer_fltr {
struct list_head list;
u32 loc;
u32 q_index;
struct ethtool_rx_flow_spec fs;
};
/**
@ -424,14 +423,12 @@ enum idpf_user_flags {
* @rss_key: RSS hash key
* @rss_lut_size: Size of RSS lookup table
* @rss_lut: RSS lookup table
* @cached_lut: Used to restore previously init RSS lut
*/
struct idpf_rss_data {
u16 rss_key_size;
u8 *rss_key;
u16 rss_lut_size;
u32 *rss_lut;
u32 *cached_lut;
};
/**
@ -558,6 +555,7 @@ struct idpf_vector_lifo {
* @max_q: Maximum possible queues
* @req_qs_chunks: Queue chunk data for requested queues
* @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
*/
struct idpf_vport_config {
@ -565,6 +563,7 @@ struct idpf_vport_config {
struct idpf_vport_max_q max_q;
struct virtchnl2_add_queues *req_qs_chunks;
spinlock_t mac_filter_list_lock;
spinlock_t flow_steer_list_lock;
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_vport_user_config_data *user_config;
struct idpf_vport_config *vport_config;
struct idpf_fsteer_fltr *f;
struct idpf_vport *vport;
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);
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) {
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);
break;
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)
if (f->loc == cmd->fs.location) {
cmd->fs.ring_cookie = f->q_index;
if (f->fs.location == cmd->fs.location) {
/* Avoid infoleak from padding: zero first,
* then assign fields
*/
memset(&cmd->fs, 0, sizeof(cmd->fs));
cmd->fs = f->fs;
err = 0;
break;
}
spin_unlock_bh(&vport_config->flow_steer_list_lock);
break;
case ETHTOOL_GRXCLSRLALL:
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) {
if (cnt == cmd->rule_cnt) {
err = -EMSGSIZE;
break;
}
rule_locs[cnt] = f->loc;
rule_locs[cnt] = f->fs.location;
cnt++;
}
if (!err)
cmd->rule_cnt = user_config->num_fsteer_fltrs;
spin_unlock_bh(&vport_config->flow_steer_list_lock);
break;
default:
break;
@ -168,7 +178,7 @@ static int idpf_add_flow_steer(struct net_device *netdev,
struct idpf_vport *vport;
u32 flow_type, q_index;
u16 num_rxq;
int err;
int err = 0;
vport = idpf_netdev_to_vport(netdev);
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)
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->count = cpu_to_le32(1);
info = &rule->rule_info[0];
@ -232,26 +265,20 @@ static int idpf_add_flow_steer(struct net_device *netdev,
goto out;
}
fltr = kzalloc(sizeof(*fltr), GFP_KERNEL);
if (!fltr) {
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;
}
/* Save a copy of the user's flow spec so ethtool can later retrieve it */
fltr->fs = *fsp;
spin_lock_bh(&vport_config->flow_steer_list_lock);
parent ? list_add(&fltr->list, &parent->list) :
list_add(&fltr->list, &user_config->flow_steer_list);
user_config->num_fsteer_fltrs++;
spin_unlock_bh(&vport_config->flow_steer_list_lock);
goto out_free_rule;
out:
kfree(fltr);
out_free_rule:
kfree(rule);
return err;
}
@ -302,17 +329,20 @@ static int idpf_del_flow_steer(struct net_device *netdev,
goto out;
}
spin_lock_bh(&vport_config->flow_steer_list_lock);
list_for_each_entry_safe(f, iter,
&user_config->flow_steer_list, list) {
if (f->loc == fsp->location) {
if (f->fs.location == fsp->location) {
list_del(&f->list);
kfree(f);
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:
kfree(rule);
return err;
@ -381,7 +411,10 @@ static u32 idpf_get_rxfh_indir_size(struct net_device *netdev)
* @netdev: network interface device structure
* @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,
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_rss_data *rss_data;
struct idpf_adapter *adapter;
struct idpf_vport *vport;
bool rxhash_ena;
int err = 0;
u16 i;
idpf_vport_ctrl_lock(netdev);
vport = idpf_netdev_to_vport(netdev);
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;
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;
if (rxfh->key)
@ -412,7 +447,7 @@ static int idpf_get_rxfh(struct net_device *netdev,
if (rxfh->indir) {
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:
@ -452,8 +487,6 @@ static int idpf_set_rxfh(struct net_device *netdev,
}
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 &&
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];
}
err = idpf_config_rss(vport);
if (test_bit(IDPF_VPORT_UP, np->state))
err = idpf_config_rss(vport);
unlock_mutex:
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++) {
struct idpf_vport *vport = adapter->vports[i];
if (!vport)
if (!vport || !vport->vdev_info)
continue;
idpf_unplug_aux_dev(vport->vdev_info->adev);

View File

@ -442,6 +442,29 @@ send_dealloc_vecs:
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
* @vconfig: Vport config structure
@ -729,6 +752,65 @@ static int idpf_init_mac_addr(struct idpf_vport *vport,
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
* @vport: main vport structure
@ -991,7 +1073,7 @@ static void idpf_vport_rel(struct idpf_vport *vport)
u16 idx = 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;
kfree(rss_data->rss_key);
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);
adapter->vport_config[idx]->req_qs_chunks = NULL;
}
kfree(vport->rx_ptype_lkup);
vport->rx_ptype_lkup = NULL;
kfree(vport);
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_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);
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_flow_steer_filters(vport);
}
if (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;
struct idpf_vport *vport;
u16 num_max_q;
int err;
if (idx == IDPF_NO_FREE_SLOT)
return NULL;
@ -1189,10 +1277,11 @@ static struct idpf_vport *idpf_vport_alloc(struct idpf_adapter *adapter,
idpf_vport_init(vport, max_q);
/* This alloc is done separate from the LUT because it's not strictly
* dependent on how many queues we have. If we change number of queues
* and soft reset we'll need a new LUT but the key can remain the same
* for as long as the vport exists.
/* LUT and key are both initialized here. Key is not strictly dependent
* on how many queues we have. If we change number of queues and soft
* reset is initiated, LUT will be freed and a new LUT will be allocated
* 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->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 */
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 */
adapter->vports[idx] = 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;
free_rss_key:
kfree(rss_data->rss_key);
free_vector_idxs:
kfree(vport->q_vector_idxs);
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_adapter *adapter = vport->adapter;
struct idpf_vport_config *vport_config;
int err;
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) {
dev_err(&adapter->pdev->dev, "Failed to initialize queue registers for vport %u: %d\n",
vport->vport_id, err);
goto queues_rel;
goto intr_deinit;
}
err = idpf_rx_bufs_init_all(vport);
if (err) {
dev_err(&adapter->pdev->dev, "Failed to initialize RX buffers for vport %u: %d\n",
vport->vport_id, err);
goto queues_rel;
goto intr_deinit;
}
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);
vport_config = adapter->vport_config[vport->idx];
if (vport_config->user_config.rss_data.rss_lut)
err = idpf_config_rss(vport);
else
err = idpf_init_rss(vport);
err = idpf_config_rss(vport);
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);
goto disable_vport;
}
@ -1497,7 +1588,7 @@ static int idpf_vport_open(struct idpf_vport *vport, bool rtnl)
if (err) {
dev_err(&adapter->pdev->dev, "Failed to complete interface up for vport %u: %d\n",
vport->vport_id, err);
goto deinit_rss;
goto disable_vport;
}
if (rtnl)
@ -1505,8 +1596,6 @@ static int idpf_vport_open(struct idpf_vport *vport, bool rtnl)
return 0;
deinit_rss:
idpf_deinit_rss(vport);
disable_vport:
idpf_send_disable_vport_msg(vport);
disable_queues:
@ -1544,7 +1633,6 @@ void idpf_init_task(struct work_struct *work)
struct idpf_vport_config *vport_config;
struct idpf_vport_max_q max_q;
struct idpf_adapter *adapter;
struct idpf_netdev_priv *np;
struct idpf_vport *vport;
u16 num_default_vports;
struct pci_dev *pdev;
@ -1579,10 +1667,15 @@ void idpf_init_task(struct work_struct *work)
goto unwind_vports;
}
err = idpf_send_get_rx_ptype_msg(vport);
if (err)
goto unwind_vports;
index = vport->idx;
vport_config = adapter->vport_config[index];
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.flow_steer_list);
@ -1590,21 +1683,11 @@ void idpf_init_task(struct work_struct *work)
err = idpf_check_supported_desc_ids(vport);
if (err) {
dev_err(&pdev->dev, "failed to get required descriptor ids\n");
goto cfg_netdev_err;
goto unwind_vports;
}
if (idpf_cfg_netdev(vport))
goto cfg_netdev_err;
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);
goto unwind_vports;
/* Spawn and return 'idpf_init_task' work queue until all the
* 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);
}
/* As all the required vports are created, clear the reset flag
* unconditionally here in case we were in reset and the link was down.
*/
/* Clear the reset and load bits as all vports are created */
clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
clear_bit(IDPF_HR_DRV_LOAD, adapter->flags);
/* Start the statistics task now */
queue_delayed_work(adapter->stats_wq, &adapter->stats_task,
msecs_to_jiffies(10 * (pdev->devfn & 0x07)));
return;
handle_err:
idpf_decfg_netdev(vport);
cfg_netdev_err:
idpf_vport_rel(vport);
adapter->vports[index] = NULL;
unwind_vports:
if (default_vport) {
for (index = 0; index < adapter->max_vports; index++) {
@ -1657,6 +1734,15 @@ unwind_vports:
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);
}
@ -1786,27 +1872,6 @@ static int idpf_check_reset_complete(struct idpf_hw *hw,
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
* @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,
* 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 device *dev = &adapter->pdev->dev;
struct net_device *netdev;
int err;
u16 i;
idpf_detach_and_close(adapter);
mutex_lock(&adapter->vport_ctrl_lock);
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 */
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);
} else if (test_and_clear_bit(IDPF_HR_FUNC_RESET, adapter->flags)) {
bool is_reset = idpf_is_reset_detected(adapter);
idpf_idc_issue_reset_event(adapter->cdev_info);
idpf_set_vport_state(adapter);
idpf_vc_core_deinit(adapter);
if (!is_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:
mutex_unlock(&adapter->vport_ctrl_lock);
/* Wait until all vports are created to init RDMA CORE AUX */
if (!err)
err = idpf_idc_init(adapter);
return err;
/* Attempt to restore netdevs and initialize RDMA CORE AUX device,
* provided vc_core_init succeeded. It is still possible that
* vports are not allocated at this point if the init task failed.
*/
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_deinit_rss(vport);
/* We're passing in vport here because we need its wait_queue
* 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
@ -2023,6 +2078,10 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
if (err)
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)
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);
}
/**
* 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
* @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) {
struct idpf_netdev_priv *np = netdev_priv(netdev);
netdev->features ^= NETIF_F_RXHASH;
err = idpf_vport_manage_rss_lut(vport);
if (err)
goto unlock_mutex;
/* If the interface is not up when changing the rxhash, update
* 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) {

View File

@ -695,9 +695,10 @@ err:
static int idpf_rx_bufs_init_singleq(struct idpf_rx_queue *rxq)
{
struct libeth_fq fq = {
.count = rxq->desc_count,
.type = LIBETH_FQE_MTU,
.nid = idpf_q_vector_to_mem(rxq->q_vector),
.count = rxq->desc_count,
.type = LIBETH_FQE_MTU,
.buf_len = IDPF_RX_MAX_BUF_SZ,
.nid = idpf_q_vector_to_mem(rxq->q_vector),
};
int ret;
@ -754,6 +755,7 @@ static int idpf_rx_bufs_init(struct idpf_buf_queue *bufq,
.truesize = bufq->truesize,
.count = bufq->desc_count,
.type = type,
.buf_len = IDPF_RX_MAX_BUF_SZ,
.hsplit = idpf_queue_has(HSPLIT_EN, bufq),
.xdp = idpf_xdp_enabled(bufq->q_vector->vport),
.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
* @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;
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;
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->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
*
* 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_rss_data *rss_data;
u32 lut_size;
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);
rss_data->rss_lut = kzalloc(lut_size, GFP_KERNEL);
if (!rss_data->rss_lut)
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;
lut_size = rss_data->rss_lut_size * sizeof(u32);
rss_data->rss_lut = kzalloc(lut_size, GFP_KERNEL);
if (!rss_data->rss_lut)
return -ENOMEM;
}
/* Fill the default RSS lut values */
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
*/
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_rss_data *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);
rss_data->rss_lut = NULL;
}

View File

@ -101,6 +101,7 @@ do { \
idx = 0; \
} while (0)
#define IDPF_RX_MAX_BUF_SZ (16384 - 128)
#define IDPF_RX_BUF_STRIDE 32
#define IDPF_RX_BUF_POST_STRIDE 16
#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);
int idpf_vport_intr_init(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_init_rss(struct idpf_vport *vport);
void idpf_deinit_rss(struct idpf_vport *vport);
int idpf_init_rss_lut(struct idpf_vport *vport);
void idpf_deinit_rss_lut(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,

View File

@ -2804,6 +2804,10 @@ int idpf_send_get_stats_msg(struct idpf_vport *vport)
* @vport: virtual port data structure
* @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.
*/
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;
int buf_size, lut_buf_size;
ssize_t reply_sz;
bool rxhash_ena;
int i;
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);
rl = kzalloc(buf_size, GFP_KERNEL);
if (!rl)
@ -2839,7 +2845,8 @@ int idpf_send_get_set_rss_lut_msg(struct idpf_vport *vport, bool get)
} else {
rl->lut_entries = cpu_to_le16(rss_data->rss_lut_size);
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;
}
@ -3570,6 +3577,7 @@ init_failed:
*/
void idpf_vc_core_deinit(struct idpf_adapter *adapter)
{
struct idpf_hw *hw = &adapter->hw;
bool remove_in_prog;
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);
kfree(hw->lan_regs);
hw->lan_regs = NULL;
kfree(adapter->vports);
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),
dev->dev);
if (!dl)
return NULL;
return devlink_priv(dl);
}

View File

@ -44,6 +44,7 @@ struct mlx5e_accel_fs_psp_prot {
struct mlx5_flow_table *ft;
struct mlx5_flow_group *miss_group;
struct mlx5_flow_handle *miss_rule;
struct mlx5_modify_hdr *rx_modify_hdr;
struct mlx5_flow_destination default_dest;
struct mlx5e_psp_rx_err rx_err;
u32 refcnt;
@ -286,13 +287,19 @@ out_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) {
mlx5_del_flow_rules(fs_prot->def_rule);
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) {
mlx5_del_flow_rules(fs_prot->miss_rule);
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;
goto out_err;
}
fs_prot->rx_modify_hdr = modify_hdr;
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
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;
out_err:
accel_psp_fs_rx_fs_destroy(fs_prot);
accel_psp_fs_rx_fs_destroy(fs, fs_prot);
out:
kvfree(flow_group_in);
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 */
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);

View File

@ -1608,12 +1608,13 @@ void mlx5e_stats_fec_get(struct mlx5e_priv *priv,
{
int mode = fec_active_mode(priv->mdev);
if (mode == MLX5E_FEC_NOFEC ||
!MLX5_CAP_PCAM_FEATURE(priv->mdev, ppcnt_statistical_group))
if (mode == MLX5E_FEC_NOFEC)
return;
fec_set_corrected_bits_total(priv, fec_stats);
fec_set_block_stats(priv, mode, fec_stats);
if (MLX5_CAP_PCAM_FEATURE(priv->mdev, ppcnt_statistical_group)) {
fec_set_corrected_bits_total(priv, fec_stats);
fec_set_block_stats(priv, mode, fec_stats);
}
if (MLX5_CAP_PCAM_REG(priv->mdev, pphcr))
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 */
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) &&
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;
}
nh_dev0 = mlx5_lag_get_next_fib_dev(ldev, fi, NULL);
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)
return err;
*status = MLX5_GET(mcia_reg, out, status);
if (*status)
if (MLX5_GET(mcia_reg, out, status)) {
if (status)
*status = MLX5_GET(mcia_reg, out, status);
return -EIO;
}
ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
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);
break;
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;
}

View File

@ -2307,14 +2307,16 @@ static void ocelot_set_aggr_pgids(struct ocelot *ocelot)
/* Now, set PGIDs for each active 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;
struct net_device *bond;
unsigned long bond_mask;
u8 aggr_idx[16];
if (!bond || (visited & BIT(lag)))
if (!ocelot_port || !ocelot_port->bond || (visited & BIT(lag)))
continue;
bond = ocelot_port->bond;
bond_mask = ocelot_get_bond_mask(ocelot, bond);
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_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:
put_net(ns_b);
put_net(ns_a);
@ -381,6 +386,9 @@ static ssize_t unlink_device_store(const struct bus_type *bus, const char *buf,
if (!peer)
goto out_put_netns;
netif_carrier_off(dev);
netif_carrier_off(peer->netdev);
err = 0;
RCU_INIT_POINTER(nsim->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),
.name = "MXL86110 Gigabit Ethernet",
.config_init = mxl86110_config_init,
.suspend = genphy_suspend,
.resume = genphy_resume,
.soft_reset = genphy_soft_reset,
.get_wol = mxl86110_get_wol,
.set_wol = mxl86110_set_wol,
.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++;
}
return 0;
return data - (u8 *)buf;
}
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_err(pegasus, drv, pegasus->net,
"%s returned %d\n", __func__, ret);
usb_free_urb(async_urb);
kfree(req);
}
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)) {
old_rss_hdr = vi->rss_hdr;
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) {
vi->rss_hdr = old_rss_hdr;
return -ENOMEM;
@ -3802,7 +3802,7 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
if (!virtnet_commit_rss_command(vi)) {
/* 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_trailer = old_rss_trailer;
@ -3810,7 +3810,7 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
queue_pairs);
return -EINVAL;
}
devm_kfree(&dev->dev, old_rss_hdr);
devm_kfree(&vi->vdev->dev, old_rss_hdr);
goto succ;
}

View File

@ -4040,7 +4040,7 @@ mac80211_hwsim_nan_dw_start(struct hrtimer *timer)
ieee80211_vif_to_wdev(data->nan_device_vif);
if (data->nan_curr_dw_band == NL80211_BAND_5GHZ)
ch = ieee80211_get_channel(hw->wiphy, 5475);
ch = ieee80211_get_channel(hw->wiphy, 5745);
else
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);
data->nan_device_vif = NULL;
spin_lock(&hwsim_radio_lock);
spin_lock_bh(&hwsim_radio_lock);
list_for_each_entry(data2, &hwsim_radios, list) {
if (data2->nan_device_vif) {
nan_cluster_running = true;
break;
}
}
spin_unlock(&hwsim_radio_lock);
spin_unlock_bh(&hwsim_radio_lock);
if (!nan_cluster_running)
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;
union mux_msg mux_msg;
struct sk_buff *skb;
int i;
if (!ipc_mux->initialized)
return;
@ -479,5 +480,10 @@ void ipc_mux_deinit(struct iosm_mux *ipc_mux)
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);
}

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,
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);

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
/* CTRL */
#define NPU_RX_DMA_DESC_LAST_MASK BIT(29)
#define NPU_RX_DMA_DESC_LEN_MASK GENMASK(28, 15)
#define NPU_RX_DMA_DESC_CUR_LEN_MASK GENMASK(14, 1)
#define NPU_RX_DMA_DESC_LAST_MASK BIT(27)
#define NPU_RX_DMA_DESC_LEN_MASK GENMASK(26, 14)
#define NPU_RX_DMA_DESC_CUR_LEN_MASK GENMASK(13, 1)
#define NPU_RX_DMA_DESC_DONE_MASK BIT(0)
/* 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_SRC_PORT_MASK GENMASK(25, 21)
#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) = { };
struct metadata_dst *tunnel_dst;
__be64 tunnel_id;
int err;
if (!vlan)
return 0;
@ -199,9 +198,13 @@ int br_handle_egress_vlan_tunnel(struct sk_buff *skb,
return 0;
skb_dst_drop(skb);
err = skb_vlan_pop(skb);
if (err)
return err;
/* For 802.1ad (QinQ), skb_vlan_pop() incorrectly moves the C-VLAN
* from payload to hwaccel after clearing S-VLAN. We only need to
* 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) {
__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) {
if (WARN_ON_ONCE(strcmp(t->name, tmpl->name) == 0)) {
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;
unsigned int tnl_hlen = skb_tnl_header_len(skb);
unsigned int delta_truesize = 0;
unsigned int delta_len = 0;
struct sk_buff *tail = NULL;
struct sk_buff *nskb, *tmp;
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);
/* 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;
list_skb = list_skb->next;
DEBUG_NET_WARN_ON_ONCE(nskb->sk);
err = 0;
delta_truesize += nskb->truesize;
if (skb_shared(nskb)) {
tmp = skb_clone(nskb, GFP_ATOMIC);
if (tmp) {
@ -4699,7 +4702,6 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
goto err_linearize;
}
skb->truesize = skb->truesize - delta_truesize;
skb->data_len = skb->data_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 level, int type)
{
struct sock_exterr_skb *serr;
struct sock_extended_err ee;
struct sk_buff *skb;
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);
serr = SKB_EXT_ERR(skb);
put_cmsg(msg, level, type, sizeof(serr->ee), &serr->ee);
/* We must use a bounce buffer for CONFIG_HARDENED_USERCOPY=y */
ee = SKB_EXT_ERR(skb)->ee;
put_cmsg(msg, level, type, sizeof(ee), &ee);
msg->msg_flags |= MSG_ERRQUEUE;
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_reset_network_header(skb);
arp = skb_put(skb, arp_hdr_len(dev));
skb_put(skb, arp_hdr_len(dev));
skb->dev = dev;
skb->protocol = htons(ETH_P_ARP);
if (!src_hw)
@ -572,12 +572,13 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
if (!dest_hw)
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)
goto out;
arp = arp_hdr(skb);
/*
* 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;
if (offset)
nf_reset_ct(skb);
return IPFRAG_OK;
}

View File

@ -828,10 +828,8 @@ out:
out_free:
if (free)
kfree(ipc.opt);
if (!err) {
icmp_out_count(sock_net(sk), user_icmph.type);
if (!err)
return len;
}
return err;
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)
goto out;
if (tp->recvmsg_inq) {
if (tp->recvmsg_inq)
*cmsg_flags = TCP_CMSG_INQ;
msg->msg_get_inq = 1;
}
timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
/* 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);
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)
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);
if (cmsg_flags & TCP_CMSG_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);
if (!skb_shared(skb)) {
skb_orphan(skb);
skb_attempt_defer_free(skb);
return;
}

View File

@ -90,6 +90,9 @@ next_interface:
/* next (or first) interface */
iter->sdata = list_prepare_entry(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 */
if (iter->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
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) {
ret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE,
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);
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);
kfree(sinfo);

View File

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

View File

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

View File

@ -89,7 +89,7 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger)
if (pf == NFPROTO_UNSPEC) {
for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) {
if (rcu_access_pointer(loggers[i][logger->type])) {
ret = -EEXIST;
ret = -EBUSY;
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);
} else {
if (rcu_access_pointer(loggers[pf][logger->type])) {
ret = -EEXIST;
ret = -EBUSY;
goto unlock;
}
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)) {
err = -EMFILE;
goto err_release_rule;
goto err_destroy_flow;
}
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:
nft_use_dec_restore(&chain->use);
err_destroy_flow:
if (flow)
nft_flow_rule_destroy(flow);
err_release_rule:

View File

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

View File

@ -48,7 +48,7 @@ static void nft_synproxy_eval_v4(const struct nft_synproxy *priv,
struct tcphdr *_tcph,
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 synproxy_net *snet = synproxy_pernet(net);
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 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 synproxy_net *snet = synproxy_pernet(net);
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 *priv = nft_obj_data(obj);
priv->info = newpriv->info;
WRITE_ONCE(priv->info, newpriv->info);
}
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 (*table_init)(struct net *net))
{
int ret = -EEXIST, af = table->af;
int ret = -EBUSY, af = table->af;
struct xt_template *t;
mutex_lock(&xt[af].mutex);

View File

@ -940,6 +940,8 @@ void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
int ret;
idr_for_each_entry_ul(idr, p, tmp, id) {
if (IS_ERR(p))
continue;
if (tc_act_in_hw(p) && !mutex_taken) {
rtnl_lock();
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;
}
/* 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);
at_ingress = skb_at_tc_ingress(skb);
if (dev == skb->dev && want_ingress == at_ingress) {
pr_notice_once("tc mirred: Loop (%s:%s --> %s:%s)\n",
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;
}
/* 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 */
nf_reset_ct(skb_to_send);
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++) {
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);
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;
struct unix_sock *u;
int copied = 0;
bool do_cmsg;
int err = 0;
long timeo;
int target;
@ -2930,9 +2929,6 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
u = unix_sk(sk);
do_cmsg = READ_ONCE(u->recvmsg_inq);
if (do_cmsg)
msg->msg_get_inq = 1;
redo:
/* Lock the socket to prevent queue disordering
* while sleeps in memcpy_tomsg
@ -3090,9 +3086,11 @@ unlock:
mutex_unlock(&u->iolock);
if (msg) {
bool do_cmsg = READ_ONCE(u->recvmsg_inq);
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);
if (do_cmsg)
put_cmsg(msg, SOL_SOCKET, SCM_INQ,

View File

@ -1787,6 +1787,10 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
} else {
newsock->state = SS_CONNECTED;
sock_graft(connected, newsock);
set_bit(SOCK_CUSTOM_SOCKOPT,
&connected->sk_socket->flags);
if (vsock_msgzerocopy_allow(vconnected->transport))
set_bit(SOCK_SUPPORT_ZC,
&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);
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.length = iwp_compat->length;
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;
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.length = iwp_compat->length;
iwp.flags = iwp_compat->flags;

View File

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

View File

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

View File

@ -52,6 +52,39 @@ cleanup_ns()
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
###
@ -113,6 +146,32 @@ if [ $? -eq 0 ]; then
exit 1
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
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 .nsim import NetdevSim, NetdevSimDev
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 NetshaperFamily, DevlinkFamily, PSPFamily
@ -26,7 +26,7 @@ __all__ = ["KSRC",
"NetNS", "NetNSEnter",
"CmdExitFailure", "fd_read_timeout", "cmd", "bkg", "defer",
"bpftool", "ip", "ethtool", "bpftrace", "rand_port",
"wait_port_listen", "wait_file",
"wait_port_listen", "wait_file", "tool",
"NetdevSim", "NetdevSimDev",
"NetshaperFamily", "DevlinkFamily", "PSPFamily", "NlError",
"YnlFamily", "EthtoolFamily", "NetdevFamily", "RtnlFamily",

View File

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

View File

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

View File

@ -5,6 +5,7 @@
#include <linux/rtnetlink.h>
#include <linux/inet_diag.h>
#include <linux/netlink.h>
#include <linux/compiler.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/tcp.h>
@ -87,7 +88,7 @@ enum {
#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);
exit(1);

View File

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

View File

@ -25,6 +25,7 @@
#include <netinet/in.h>
#include <linux/tcp.h>
#include <linux/compiler.h>
static int pf = AF_INET;
@ -127,7 +128,7 @@ struct so_state {
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
static void die_perror(const char *msg)
static void __noreturn die_perror(const char *msg)
{
perror(msg);
exit(1);
@ -139,7 +140,7 @@ static void die_usage(int r)
exit(r);
}
static void xerror(const char *fmt, ...)
static void __noreturn xerror(const char *fmt, ...)
{
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"
# 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
PKTGEN_SCRIPT_PATHS="
@ -420,6 +420,18 @@ race_repeat 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='
flush ruleset
@ -1954,6 +1966,37 @@ EOF
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() {
eval test_bug_"${subtest}"
}

View File

@ -1098,5 +1098,52 @@
"teardown": [
"$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);
}
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[] = {
{
.name = "SOCK_STREAM connection reset",
@ -2371,6 +2398,11 @@ static struct test_case test_cases[] = {
.run_client = test_seqpacket_unread_bytes_client,
.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,
},
{},
};