summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/bonding/bond_alb.c34
-rw-r--r--drivers/net/bonding/bond_main.c18
-rw-r--r--drivers/net/bonding/bond_options.c4
-rw-r--r--drivers/net/dsa/bcm_sf2_cfp.c2
-rw-r--r--drivers/net/dsa/lantiq/lantiq_gswip.h2
-rw-r--r--drivers/net/dsa/mt7530.c16
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c16
-rw-r--r--drivers/net/dsa/mv88e6xxx/tcflower.c2
-rw-r--r--drivers/net/ethernet/airoha/airoha_eth.h2
-rw-r--r--drivers/net/ethernet/alibaba/eea/eea_adminq.c7
-rw-r--r--drivers/net/ethernet/alibaba/eea/eea_net.c8
-rw-r--r--drivers/net/ethernet/alibaba/eea/eea_pci.c2
-rw-r--r--drivers/net/ethernet/alibaba/eea/eea_ring.c2
-rw-r--r--drivers/net/ethernet/alibaba/eea/eea_rx.c5
-rw-r--r--drivers/net/ethernet/alibaba/eea/eea_tx.c3
-rw-r--r--drivers/net/ethernet/allwinner/sun4i-emac.c2
-rw-r--r--drivers/net/ethernet/amd/pds_core/core.c3
-rw-r--r--drivers/net/ethernet/amd/pds_core/fw.c16
-rw-r--r--drivers/net/ethernet/amd/pds_core/main.c10
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-dev.c3
-rw-r--r--drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c4
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c99
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h3
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c21
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_gso.h6
-rw-r--r--drivers/net/ethernet/cadence/macb.h3
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c47
-rw-r--r--drivers/net/ethernet/cadence/macb_ptp.c5
-rw-r--r--drivers/net/ethernet/cisco/enic/enic.h26
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_admin.c2
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c31
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_mbox.c309
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_mbox.h2
-rw-r--r--drivers/net/ethernet/cortina/gemini.c77
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c5
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c4
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.c9
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sched.c4
-rw-r--r--drivers/net/ethernet/intel/ice/ice_trace.h64
-rw-r--r--drivers/net/ethernet/intel/ice/ice_type.h2
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_main.c5
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_txrx.c34
-rw-r--r--drivers/net/ethernet/intel/libie/controlq.c3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c13
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/mcs.c10
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.c33
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c10
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/qos.c60
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.c18
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.h4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/port.c15
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/port.h4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c13
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.c52
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rx.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_stats.c51
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c37
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c19
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c34
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_irq.c2
-rw-r--r--drivers/net/ethernet/micrel/ks8851_common.c8
-rw-r--r--drivers/net/ethernet/microsoft/mana/gdma_main.c8
-rw-r--r--drivers/net/ethernet/microsoft/mana/mana_bpf.c1
-rw-r--r--drivers/net/ethernet/microsoft/mana/mana_en.c24
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c19
-rw-r--r--drivers/net/ethernet/oa_tc6.c258
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_txrx.c13
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c93
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c1
-rw-r--r--drivers/net/gtp.c5
-rw-r--r--drivers/net/ieee802154/cc2520.c5
-rw-r--r--drivers/net/ieee802154/mac802154_hwsim.c10
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c4
-rw-r--r--drivers/net/mctp/mctp-i3c.c9
-rw-r--r--drivers/net/net_failover.c2
-rw-r--r--drivers/net/ntb_netdev.c50
-rw-r--r--drivers/net/phy/dp83867.c3
-rw-r--r--drivers/net/phy/dp83td510.c3
-rw-r--r--drivers/net/phy/mediatek/mtk-ge.c29
-rw-r--r--drivers/net/phy/phylink.c2
-rw-r--r--drivers/net/ppp/ppp_async.c89
-rw-r--r--drivers/net/ppp/ppp_synctty.c97
-rw-r--r--drivers/net/usb/cx82310_eth.c1
-rw-r--r--drivers/net/usb/hso.c2
-rw-r--r--drivers/net/usb/qmi_wwan.c2
-rw-r--r--drivers/net/vxlan/vxlan_core.c13
-rw-r--r--drivers/net/vxlan/vxlan_mdb.c8
-rw-r--r--drivers/net/wireless/ath/ath12k/ahb.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/regulatory.c3
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mcu.c9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/regd.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/main.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/regd.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c3
-rw-r--r--drivers/net/wireless/morsemicro/mm81x/mac.c9
-rw-r--r--drivers/net/wireless/morsemicro/mm81x/yaps.c10
-rw-r--r--drivers/net/wireless/nxp/nxpwifi/cfg80211.c14
-rw-r--r--drivers/net/wireless/nxp/nxpwifi/cmdevt.c2
-rw-r--r--drivers/net/wireless/nxp/nxpwifi/ie.c14
-rw-r--r--drivers/net/wireless/nxp/nxpwifi/init.c2
-rw-r--r--drivers/net/wireless/nxp/nxpwifi/main.c8
-rw-r--r--drivers/net/wireless/nxp/nxpwifi/scan.c13
-rw-r--r--drivers/net/wireless/nxp/nxpwifi/sta_cfg.c2
-rw-r--r--drivers/net/wireless/nxp/nxpwifi/sta_cmd.c2
-rw-r--r--drivers/net/wireless/nxp/nxpwifi/uap_event.c2
116 files changed, 1369 insertions, 837 deletions
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 839f7482dc18..43ac8e28e418 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -678,9 +678,15 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
if (arp->op_code == htons(ARPOP_REPLY)) {
/* the arp must be sent on the selected rx channel */
tx_slave = rlb_choose_channel(skb, bond, arp);
- if (tx_slave)
+ if (tx_slave &&
+ !ether_addr_equal_64bits(arp->mac_src,
+ tx_slave->dev->dev_addr)) {
+ if (unlikely(skb_cow_head(skb, 0)))
+ return NULL;
+ arp = (struct arp_pkt *)skb_network_header(skb);
bond_hw_addr_copy(arp->mac_src, tx_slave->dev->dev_addr,
tx_slave->dev->addr_len);
+ }
netdev_dbg(bond->dev, "(slave %s): Server sent ARP Reply packet\n",
tx_slave ? tx_slave->dev->name : "NULL");
} else if (arp->op_code == htons(ARPOP_REQUEST)) {
@@ -875,7 +881,7 @@ static int rlb_initialize(struct bonding *bond)
spin_unlock_bh(&bond->mode_lock);
/* register to receive ARPs */
- bond->recv_probe = rlb_arp_recv;
+ WRITE_ONCE(bond->recv_probe, rlb_arp_recv);
return 0;
}
@@ -1281,10 +1287,10 @@ unwind:
}
/* determine if the packet is NA or NS */
-static bool alb_determine_nd(struct sk_buff *skb, struct bonding *bond)
+static bool alb_determine_nd(struct sk_buff *skb)
{
- struct ipv6hdr *ip6hdr;
- struct icmp6hdr *hdr;
+ const struct ipv6hdr *ip6hdr;
+ const struct icmp6hdr *hdr;
if (!pskb_network_may_pull(skb, sizeof(*ip6hdr)))
return true;
@@ -1296,7 +1302,8 @@ static bool alb_determine_nd(struct sk_buff *skb, struct bonding *bond)
if (!pskb_network_may_pull(skb, sizeof(*ip6hdr) + sizeof(*hdr)))
return true;
- hdr = icmp6_hdr(skb);
+ ip6hdr = ipv6_hdr(skb);
+ hdr = (const struct icmp6hdr *)(ip6hdr + 1);
return hdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT ||
hdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION;
}
@@ -1339,7 +1346,6 @@ static netdev_tx_t bond_do_alb_xmit(struct sk_buff *skb, struct bonding *bond,
struct slave *tx_slave)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
- struct ethhdr *eth_data = eth_hdr(skb);
if (!tx_slave) {
/* unbalanced or unassigned, send through primary */
@@ -1350,7 +1356,9 @@ static netdev_tx_t bond_do_alb_xmit(struct sk_buff *skb, struct bonding *bond,
if (tx_slave && bond_slave_can_tx(tx_slave)) {
if (tx_slave != rcu_access_pointer(bond->curr_active_slave)) {
- ether_addr_copy(eth_data->h_source,
+ if (unlikely(skb_cow_head(skb, 0)))
+ return bond_tx_drop(bond->dev, skb);
+ ether_addr_copy(skb_eth_hdr(skb)->h_source,
tx_slave->dev->dev_addr);
}
@@ -1374,14 +1382,13 @@ struct slave *bond_xmit_tlb_slave_get(struct bonding *bond,
struct ethhdr *eth_data;
u32 hash_index;
- skb_reset_mac_header(skb);
- eth_data = eth_hdr(skb);
+ eth_data = skb_eth_hdr(skb);
/* Do not TX balance any multicast or broadcast */
if (!is_multicast_ether_addr(eth_data->h_dest)) {
switch (skb->protocol) {
case htons(ETH_P_IPV6):
- if (alb_determine_nd(skb, bond))
+ if (alb_determine_nd(skb))
break;
fallthrough;
case htons(ETH_P_IP):
@@ -1427,8 +1434,7 @@ struct slave *bond_xmit_alb_slave_get(struct bonding *bond,
u32 hash_index = 0;
int hash_size = 0;
- skb_reset_mac_header(skb);
- eth_data = eth_hdr(skb);
+ eth_data = skb_eth_hdr(skb);
switch (ntohs(skb->protocol)) {
case ETH_P_IP: {
@@ -1467,7 +1473,7 @@ struct slave *bond_xmit_alb_slave_get(struct bonding *bond,
break;
}
- if (alb_determine_nd(skb, bond)) {
+ if (alb_determine_nd(skb)) {
do_tx_balance = false;
break;
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index ef9eb0c53c66..a9bff7663eec 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1245,7 +1245,7 @@ static void bond_peer_notify_may_events(struct bonding *bond, bool force)
}
if (notified || force)
- bond->send_peer_notif--;
+ WRITE_ONCE(bond->send_peer_notif, bond->send_peer_notif - 1);
}
/**
@@ -2284,7 +2284,7 @@ skip_mac_set:
}
}
- bond->slave_cnt++;
+ WRITE_ONCE(bond->slave_cnt, bond->slave_cnt + 1);
netdev_compute_master_upper_features(bond->dev, true);
bond_set_carrier(bond);
@@ -2517,9 +2517,7 @@ static int __bond_release_one(struct net_device *bond_dev,
bond_alb_deinit_slave(bond, slave);
}
- if (all) {
- RCU_INIT_POINTER(bond->curr_active_slave, NULL);
- } else if (oldcurrent == slave) {
+ if (!all && oldcurrent == slave) {
/* Note that we hold RTNL over this sequence, so there
* is no concern that another slave add/remove event
* will interfere.
@@ -2533,7 +2531,7 @@ static int __bond_release_one(struct net_device *bond_dev,
unblock_netpoll_tx();
synchronize_rcu();
- bond->slave_cnt--;
+ WRITE_ONCE(bond->slave_cnt, bond->slave_cnt - 1);
if (!bond_has_slaves(bond)) {
call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
@@ -4385,13 +4383,13 @@ static int bond_open(struct net_device *bond_dev)
if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
queue_delayed_work(bond->wq, &bond->arp_work, 0);
- bond->recv_probe = bond_rcv_validate;
+ WRITE_ONCE(bond->recv_probe, bond_rcv_validate);
}
if (BOND_MODE(bond) == BOND_MODE_8023AD) {
queue_delayed_work(bond->wq, &bond->ad_work, 0);
/* register to receive LACPDUs */
- bond->recv_probe = bond_3ad_lacpdu_recv;
+ WRITE_ONCE(bond->recv_probe, bond_3ad_lacpdu_recv);
bond_3ad_initiate_agg_selection(bond, 1);
bond_for_each_slave(bond, slave, iter)
@@ -4413,7 +4411,7 @@ static int bond_close(struct net_device *bond_dev)
struct slave *slave;
bond_work_cancel_all(bond);
- bond->send_peer_notif = 0;
+ WRITE_ONCE(bond->send_peer_notif, 0);
WRITE_ONCE(bond->recv_probe, NULL);
/* Wait for any in-flight RX handlers */
@@ -5118,7 +5116,7 @@ static void bond_skip_slave(struct bond_up_slave *slaves,
if (skipslave == slaves->arr[idx]) {
slaves->arr[idx] =
slaves->arr[slaves->count - 1];
- slaves->count--;
+ WRITE_ONCE(slaves->count, slaves->count - 1);
break;
}
}
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 36b8d89387ee..9efadeff6a22 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -1147,11 +1147,11 @@ static int bond_option_arp_interval_set(struct bonding *bond,
*/
if (!newval->value) {
if (bond->params.arp_validate)
- bond->recv_probe = NULL;
+ WRITE_ONCE(bond->recv_probe, NULL);
cancel_delayed_work_sync(&bond->arp_work);
} else {
/* arp_validate can be set only in active-backup mode */
- bond->recv_probe = bond_rcv_validate;
+ WRITE_ONCE(bond->recv_probe, bond_rcv_validate);
cancel_delayed_work_sync(&bond->mii_work);
queue_delayed_work(bond->wq, &bond->arp_work, 0);
}
diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c
index 50d3a818eb1b..84a086c3e99b 100644
--- a/drivers/net/dsa/bcm_sf2_cfp.c
+++ b/drivers/net/dsa/bcm_sf2_cfp.c
@@ -1088,6 +1088,8 @@ static int bcm_sf2_cfp_rule_get_all(struct bcm_sf2_priv *priv,
unsigned int index = 1, rules_cnt = 0;
for_each_set_bit_from(index, priv->cfp.unique, priv->num_cfp_rules) {
+ if (rules_cnt == nfc->rule_cnt)
+ return -EMSGSIZE;
rule_locs[rules_cnt] = index;
rules_cnt++;
}
diff --git a/drivers/net/dsa/lantiq/lantiq_gswip.h b/drivers/net/dsa/lantiq/lantiq_gswip.h
index bc3686faad0d..0b75be14dc10 100644
--- a/drivers/net/dsa/lantiq/lantiq_gswip.h
+++ b/drivers/net/dsa/lantiq/lantiq_gswip.h
@@ -42,7 +42,7 @@
#define GSWIP_MDIO_PHY_FDUP_DIS 0x0600
#define GSWIP_MDIO_PHY_FCONTX_MASK 0x0180
#define GSWIP_MDIO_PHY_FCONTX_AUTO 0x0000
-#define GSWIP_MDIO_PHY_FCONTX_EN 0x0100
+#define GSWIP_MDIO_PHY_FCONTX_EN 0x0080
#define GSWIP_MDIO_PHY_FCONTX_DIS 0x0180
#define GSWIP_MDIO_PHY_FCONRX_MASK 0x0060
#define GSWIP_MDIO_PHY_FCONRX_AUTO 0x0000
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 2b7be091c056..3e61eb3c2b1e 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -3172,23 +3172,31 @@ static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port,
config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
+ priv->info->mac_port_get_caps(ds, port, config);
+
/* The EN7528 GPHYs report EEE capability, but negotiating EEE with
* common link partners (e.g. Realtek GbE NICs) results in an unstable
* link with dropped frames. Leave the LPI capabilities empty so that
* phylink disables EEE on these PHYs and refuses to enable it from
* userspace.
*/
- if (priv->id != ID_EN7528) {
+ if (priv->id != ID_EN7528 &&
+ config->mac_capabilities & (MAC_100FD | MAC_1000FD)) {
u32 eeecr = mt7530_read(priv, MT753X_PMEEECR_P(port));
- config->lpi_capabilities = MAC_100FD | MAC_1000FD | MAC_2500FD;
+ /* LPI above 1 Gbps is not supported */
+ config->lpi_capabilities = config->mac_capabilities &
+ (MAC_100FD | MAC_1000FD);
+ phy_interface_copy(config->lpi_interfaces,
+ config->supported_interfaces);
+ __clear_bit(PHY_INTERFACE_MODE_2500BASEX,
+ config->lpi_interfaces);
+
/* tx_lpi_timer should be in microseconds. The time units for
* LPI threshold are unspecified.
*/
config->lpi_timer_default = FIELD_GET(LPI_THRESH_MASK, eeecr);
}
-
- priv->info->mac_port_get_caps(ds, port, config);
}
static int mt753x_pcs_validate(struct phylink_pcs *pcs,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 80b877c74513..7f68a0c55802 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2438,6 +2438,7 @@ static int mv88e6xxx_get_rxnfc(struct dsa_switch *ds, int port,
struct ethtool_rx_flow_spec *fs = &rxnfc->fs;
struct mv88e6xxx_chip *chip = ds->priv;
struct mv88e6xxx_policy *policy;
+ u32 cnt = 0;
int err;
int id;
@@ -2463,11 +2464,18 @@ static int mv88e6xxx_get_rxnfc(struct dsa_switch *ds, int port,
break;
case ETHTOOL_GRXCLSRLALL:
rxnfc->data = 0;
- rxnfc->rule_cnt = 0;
- idr_for_each_entry(&chip->policies, policy, id)
- if (policy->port == port)
- rule_locs[rxnfc->rule_cnt++] = id;
err = 0;
+ idr_for_each_entry(&chip->policies, policy, id) {
+ if (policy->port != port)
+ continue;
+ if (cnt == rxnfc->rule_cnt) {
+ err = -EMSGSIZE;
+ break;
+ }
+ rule_locs[cnt++] = id;
+ }
+ if (!err)
+ rxnfc->rule_cnt = cnt;
break;
default:
err = -EOPNOTSUPP;
diff --git a/drivers/net/dsa/mv88e6xxx/tcflower.c b/drivers/net/dsa/mv88e6xxx/tcflower.c
index d67604a55b9f..2ddfeaaa0690 100644
--- a/drivers/net/dsa/mv88e6xxx/tcflower.c
+++ b/drivers/net/dsa/mv88e6xxx/tcflower.c
@@ -97,7 +97,7 @@ int mv88e6xxx_cls_flower_add(struct dsa_switch *ds, int port,
goto err_unlock;
}
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ entry = kzalloc_obj(*entry);
if (!entry) {
err = -ENOMEM;
goto err_unlock;
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index fa9a8edce22f..8277c1c87bb3 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -538,7 +538,7 @@ struct airoha_wdma_info {
/* RX queue to IRQ mapping: BIT(q) in IRQ(n) */
#define RX_IRQ0_BANK_PIN_MASK 0x839f
-#define RX_IRQ1_BANK_PIN_MASK 0x7fe00000
+#define RX_IRQ1_BANK_PIN_MASK 0xffe00000
#define RX_IRQ2_BANK_PIN_MASK 0x20
#define RX_IRQ3_BANK_PIN_MASK 0x40
#define RX_IRQ_BANK_PIN_MASK(_n) \
diff --git a/drivers/net/ethernet/alibaba/eea/eea_adminq.c b/drivers/net/ethernet/alibaba/eea/eea_adminq.c
index dfad1bdbc44d..73d0caf25700 100644
--- a/drivers/net/ethernet/alibaba/eea/eea_adminq.c
+++ b/drivers/net/ethernet/alibaba/eea/eea_adminq.c
@@ -439,8 +439,7 @@ int eea_adminq_dev_status(struct eea_net *enet,
q_num = enet->cfg.rx_ring_num + enet->cfg.tx_ring_num + 1;
io_num = enet->cfg.rx_ring_num + enet->cfg.tx_ring_num;
- req = kcalloc(q_num, sizeof(struct eea_aq_queue_drv_status),
- GFP_KERNEL);
+ req = kzalloc_objs(struct eea_aq_queue_drv_status, q_num);
if (!req)
return -ENOMEM;
@@ -486,11 +485,11 @@ void eea_adminq_config_host_info(struct eea_net *enet)
struct eea_aq_host_info_rep *rep;
int rc = -ENOMEM;
- cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+ cfg = kzalloc_obj(*cfg);
if (!cfg)
return;
- rep = kzalloc(sizeof(*rep), GFP_KERNEL);
+ rep = kzalloc_obj(*rep);
if (!rep)
goto err_free_cfg;
diff --git a/drivers/net/ethernet/alibaba/eea/eea_net.c b/drivers/net/ethernet/alibaba/eea/eea_net.c
index 63e68580de94..0af6c95b5e63 100644
--- a/drivers/net/ethernet/alibaba/eea/eea_net.c
+++ b/drivers/net/ethernet/alibaba/eea/eea_net.c
@@ -62,7 +62,7 @@ static int eea_alloc_irq_blks(struct eea_net *enet)
num = enet->edev->rx_num;
- irq_blks = kvcalloc(num, sizeof(*blk), GFP_KERNEL);
+ irq_blks = kvzalloc_objs(*blk, num);
if (!irq_blks)
return -ENOMEM;
@@ -194,11 +194,11 @@ static int eea_alloc_rxtx_q_mem(struct eea_net_init_ctx *ctx)
struct eea_net_tx *tx;
int err, i;
- ctx->tx = kvcalloc(ctx->cfg.tx_ring_num, sizeof(*ctx->tx), GFP_KERNEL);
+ ctx->tx = kvzalloc_objs(*ctx->tx, ctx->cfg.tx_ring_num);
if (!ctx->tx)
return -ENOMEM;
- ctx->rx = kvcalloc(ctx->cfg.rx_ring_num, sizeof(*ctx->rx), GFP_KERNEL);
+ ctx->rx = kvzalloc_objs(*ctx->rx, ctx->cfg.rx_ring_num);
if (!ctx->rx)
goto err_free_tx;
@@ -601,7 +601,7 @@ static int eea_netdev_init_features(struct net_device *netdev,
int err;
u32 mtu;
- cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+ cfg = kzalloc_obj(*cfg);
if (!cfg)
return -ENOMEM;
diff --git a/drivers/net/ethernet/alibaba/eea/eea_pci.c b/drivers/net/ethernet/alibaba/eea/eea_pci.c
index 9872e360dd5d..c625b58b26f0 100644
--- a/drivers/net/ethernet/alibaba/eea/eea_pci.c
+++ b/drivers/net/ethernet/alibaba/eea/eea_pci.c
@@ -651,7 +651,7 @@ static int eea_pci_probe(struct pci_dev *pci_dev,
struct eea_device *edev;
int err;
- ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL);
+ ep_dev = kzalloc_obj(*ep_dev);
if (!ep_dev)
return -ENOMEM;
diff --git a/drivers/net/ethernet/alibaba/eea/eea_ring.c b/drivers/net/ethernet/alibaba/eea/eea_ring.c
index 99dcabd094b8..fac7d4647ecb 100644
--- a/drivers/net/ethernet/alibaba/eea/eea_ring.c
+++ b/drivers/net/ethernet/alibaba/eea/eea_ring.c
@@ -217,7 +217,7 @@ struct eea_ring *eea_ering_alloc(u32 index, u32 num, struct eea_device *edev,
if (!cq_desc_size || !is_power_of_2(cq_desc_size))
return NULL;
- ering = kzalloc(sizeof(*ering), GFP_KERNEL);
+ ering = kzalloc_obj(*ering);
if (!ering)
return NULL;
diff --git a/drivers/net/ethernet/alibaba/eea/eea_rx.c b/drivers/net/ethernet/alibaba/eea/eea_rx.c
index a3f0d2a79ad8..5dfb7cb2ba6d 100644
--- a/drivers/net/ethernet/alibaba/eea/eea_rx.c
+++ b/drivers/net/ethernet/alibaba/eea/eea_rx.c
@@ -764,7 +764,7 @@ struct eea_net_rx *eea_alloc_rx(struct eea_net_init_ctx *ctx, u32 idx)
struct eea_net_rx *rx;
int err;
- rx = kzalloc(sizeof(*rx), GFP_KERNEL);
+ rx = kzalloc_obj(*rx);
if (!rx)
return rx;
@@ -786,8 +786,7 @@ struct eea_net_rx *eea_alloc_rx(struct eea_net_init_ctx *ctx, u32 idx)
rx->dma_dev = ctx->edev->dma_dev;
/* meta */
- rx->meta = kvcalloc(ctx->cfg.rx_ring_depth,
- sizeof(*rx->meta), GFP_KERNEL);
+ rx->meta = kvzalloc_objs(*rx->meta, ctx->cfg.rx_ring_depth);
if (!rx->meta)
goto err_free_rx;
diff --git a/drivers/net/ethernet/alibaba/eea/eea_tx.c b/drivers/net/ethernet/alibaba/eea/eea_tx.c
index 85fb0e9ca5ba..c9292bca1a8b 100644
--- a/drivers/net/ethernet/alibaba/eea/eea_tx.c
+++ b/drivers/net/ethernet/alibaba/eea/eea_tx.c
@@ -480,8 +480,7 @@ int eea_alloc_tx(struct eea_net_init_ctx *ctx, struct eea_net_tx *tx, u32 idx)
tx->dma_dev = ctx->edev->dma_dev;
/* meta */
- tx->meta = kvcalloc(ctx->cfg.tx_ring_depth,
- sizeof(*tx->meta), GFP_KERNEL);
+ tx->meta = kvzalloc_objs(*tx->meta, ctx->cfg.tx_ring_depth);
if (!tx->meta)
goto err_free_tx;
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
index 942454e29488..0ba67a55705d 100644
--- a/drivers/net/ethernet/allwinner/sun4i-emac.c
+++ b/drivers/net/ethernet/allwinner/sun4i-emac.c
@@ -1067,6 +1067,7 @@ static int emac_probe(struct platform_device *pdev)
return 0;
out_release_sram:
+ of_node_put(db->phy_node);
sunxi_sram_release(&pdev->dev);
out_clk_disable_unprepare:
clk_disable_unprepare(db->clk);
@@ -1094,6 +1095,7 @@ static void emac_remove(struct platform_device *pdev)
}
unregister_netdev(ndev);
+ of_node_put(db->phy_node);
sunxi_sram_release(&pdev->dev);
clk_disable_unprepare(db->clk);
irq_dispose_mapping(ndev->irq);
diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c
index 922e3ec8af1b..419e4b6ac983 100644
--- a/drivers/net/ethernet/amd/pds_core/core.c
+++ b/drivers/net/ethernet/amd/pds_core/core.c
@@ -810,8 +810,7 @@ void pdsc_host_mem_add(struct pdsc *pdsc)
if (count == 0)
return;
- pdsc->host_mem_reqs = kzalloc_objs(*pdsc->host_mem_reqs, count,
- GFP_KERNEL);
+ pdsc->host_mem_reqs = kzalloc_objs(*pdsc->host_mem_reqs, count);
if (!pdsc->host_mem_reqs) {
dev_err(pdsc->dev, "failed to alloc host_mem_reqs array\n");
return;
diff --git a/drivers/net/ethernet/amd/pds_core/fw.c b/drivers/net/ethernet/amd/pds_core/fw.c
index 5ccf017f6af4..7fe4594e9f9b 100644
--- a/drivers/net/ethernet/amd/pds_core/fw.c
+++ b/drivers/net/ethernet/amd/pds_core/fw.c
@@ -171,8 +171,10 @@ pdsc_legacy_firmware_update(struct pdsc *pdsc,
dev_info(pdsc->dev, "Installing firmware\n");
- if (!pdsc->cmd_regs)
+ if (!pdsc->cmd_regs) {
+ NL_SET_ERR_MSG_MOD(extack, "BARs not mapped");
return -ENXIO;
+ }
dl = priv_to_devlink(pdsc);
devlink_flash_update_status_notify(dl, "Preparing to flash",
@@ -198,6 +200,12 @@ pdsc_legacy_firmware_update(struct pdsc *pdsc,
copy_sz = min_t(unsigned int, buf_sz, fw->size - offset);
mutex_lock(&pdsc->devcmd_lock);
+ if (!pdsc->cmd_regs) {
+ mutex_unlock(&pdsc->devcmd_lock);
+ err = -ENXIO;
+ NL_SET_ERR_MSG_MOD(extack, "Device reset during flash");
+ goto err_out;
+ }
memcpy_toio(&pdsc->cmd_regs->data, fw->data + offset, copy_sz);
err = pdsc_devcmd_fw_download_locked(pdsc, data_addr,
offset, copy_sz);
@@ -382,7 +390,7 @@ static int pdsc_send_package_data(struct pldmfw *context, const u8 *data,
if (!length)
return 0;
- deferred = kmalloc_obj(*deferred, GFP_KERNEL);
+ deferred = kmalloc_obj(*deferred);
if (!deferred)
return -ENOMEM;
@@ -505,7 +513,7 @@ static int pdsc_send_component_table(struct pldmfw *context,
component->version_string, component->index,
component->component_size, transfer_flag);
- component_priv = kzalloc_obj(*component_priv, GFP_KERNEL);
+ component_priv = kzalloc_obj(*component_priv);
if (!component_priv)
return -ENOMEM;
@@ -710,7 +718,7 @@ static int pdsc_flash_component_chunk(struct pdsc *pdsc, struct device *dev,
u8 *component_data;
int err;
- deferred = kmalloc_obj(*deferred, GFP_KERNEL);
+ deferred = kmalloc_obj(*deferred);
if (!deferred)
return -ENOMEM;
diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c
index bb79e7476370..a971c66d36f9 100644
--- a/drivers/net/ethernet/amd/pds_core/main.c
+++ b/drivers/net/ethernet/amd/pds_core/main.c
@@ -513,8 +513,12 @@ static void pdsc_reset_prepare(struct pci_dev *pdev)
pdsc_auxbus_dev_del(pdsc, pdsc, &pdsc->padev);
}
- pdsc_unmap_bars(pdsc);
- pci_release_regions(pdev);
+ if (!pdev->is_virtfn) {
+ mutex_lock(&pdsc->devcmd_lock);
+ pdsc_unmap_bars(pdsc);
+ mutex_unlock(&pdsc->devcmd_lock);
+ pci_release_regions(pdev);
+ }
if (pci_is_enabled(pdev))
pci_disable_device(pdev);
pdsc_deferred_dma_free(pdsc);
@@ -543,7 +547,9 @@ static void pdsc_reset_done(struct pci_dev *pdev)
return;
}
+ mutex_lock(&pdsc->devcmd_lock);
err = pdsc_map_bars(pdsc);
+ mutex_unlock(&pdsc->devcmd_lock);
if (err)
return;
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 2de974213090..e2e850c1b90b 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -3400,7 +3400,7 @@ static void xgbe_enable_rx(struct xgbe_prv_data *pdata)
XGMAC_IOWRITE(pdata, MAC_RQC0R, reg_val);
/* Enable MAC Rx */
- XGMAC_IOWRITE_BITS(pdata, MAC_RCR, DCRCC, 1);
+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, DCRCC, 0);
XGMAC_IOWRITE_BITS(pdata, MAC_RCR, CST, 1);
XGMAC_IOWRITE_BITS(pdata, MAC_RCR, ACS, 1);
XGMAC_IOWRITE_BITS(pdata, MAC_RCR, RE, 1);
@@ -3411,7 +3411,6 @@ static void xgbe_disable_rx(struct xgbe_prv_data *pdata)
unsigned int i;
/* Disable MAC Rx */
- XGMAC_IOWRITE_BITS(pdata, MAC_RCR, DCRCC, 0);
XGMAC_IOWRITE_BITS(pdata, MAC_RCR, CST, 0);
XGMAC_IOWRITE_BITS(pdata, MAC_RCR, ACS, 0);
XGMAC_IOWRITE_BITS(pdata, MAC_RCR, RE, 0);
diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
index ed0977832ce4..f2176ef3a127 100644
--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
+++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
@@ -148,8 +148,9 @@ static int tx_spb_ring_full(struct bcmasp_intf *intf, int cnt)
int next_index, i;
/* Check if we have enough room for cnt descriptors */
+ next_index = intf->tx_spb_index;
for (i = 0; i < cnt; i++) {
- next_index = incr_ring(intf->tx_spb_index, DESC_RING_COUNT);
+ next_index = incr_ring(next_index, DESC_RING_COUNT);
if (next_index == intf->tx_spb_clean_index)
return 1;
}
@@ -301,6 +302,7 @@ static netdev_tx_t bcmasp_xmit(struct sk_buff *skb, struct net_device *dev)
txcb->bytes_sent = total_bytes;
dma_unmap_addr_set(txcb, dma_addr, mapping);
dma_unmap_len_set(txcb, dma_len, size);
+ txcb->last = false;
if (!i) {
desc->flags |= DESC_SOF;
if (csum_hw)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index d59bcca73a2b..d7728d0c5b6e 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -462,6 +462,16 @@ u16 bnxt_xmit_get_cfa_action(struct sk_buff *skb)
static void bnxt_txr_db_kick(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
u16 prod)
{
+ /* If the most recent BD has its completion suppressed, unset the bit
+ * so that a completion is generated, otherwise nothing is left to
+ * clean the ring and wake the queue.
+ */
+ if (txr->kick_txbd0) {
+ txr->kick_txbd0->tx_bd_len_flags_type &=
+ cpu_to_le32(~TX_BD_FLAGS_NO_CMPL);
+ txr->kick_txbd0 = NULL;
+ }
+
/* Sync BD data before updating doorbell */
wmb();
bnxt_db_write(bp, &txr->tx_db, prod);
@@ -485,7 +495,6 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct bnxt_sw_tx_bd *tx_buf;
__le32 lflags = 0;
skb_frag_t *frag;
- netdev_tx_t ret;
i = skb_get_queue_mapping(skb);
if (unlikely(i >= bp->tx_nr_rings)) {
@@ -509,11 +518,22 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb_is_gso(skb) &&
(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) &&
!(bp->flags & BNXT_FLAG_UDP_GSO_CAP)) {
- ret = bnxt_sw_udp_gso_xmit(bp, txr, txq, skb);
- if (txr->kick_pending)
+ int rc = bnxt_sw_udp_gso_xmit(bp, txr, txq, skb);
+
+ /* if SW USO queued a packet, the doorbell will be written
+ * below and there is no reason to track the last BD with
+ * suppressed completions
+ */
+ if (rc > 0)
+ txr->kick_txbd0 = NULL;
+
+ /* if a packet was queued by SW USO or a doorbell was pending
+ * from a previous xmit that was deferred, write the doorbell.
+ */
+ if (rc > 0 || txr->kick_pending)
bnxt_txr_db_kick(bp, txr, txr->tx_prod);
- return ret;
+ return rc < 0 ? NETDEV_TX_BUSY : NETDEV_TX_OK;
}
free_size = bnxt_tx_avail(bp, txr);
@@ -751,23 +771,23 @@ normal_tx:
prod = NEXT_TX(prod);
WRITE_ONCE(txr->tx_prod, prod);
+ txr->kick_txbd0 = NULL;
if (!netdev_xmit_more() || netif_xmit_stopped(txq)) {
bnxt_txr_db_kick(bp, txr, prod);
} else {
- if (free_size >= bp->tx_wake_thresh)
+ if (free_size >= bp->tx_wake_thresh) {
txbd0->tx_bd_len_flags_type |=
cpu_to_le32(TX_BD_FLAGS_NO_CMPL);
+ txr->kick_txbd0 = txbd0;
+ }
txr->kick_pending = 1;
}
tx_done:
if (unlikely(bnxt_tx_avail(bp, txr) <= MAX_SKB_FRAGS + 1)) {
- if (netdev_xmit_more() && !tx_buf->is_push) {
- txbd0->tx_bd_len_flags_type &=
- cpu_to_le32(~TX_BD_FLAGS_NO_CMPL);
+ if (txr->kick_pending)
bnxt_txr_db_kick(bp, txr, prod);
- }
netif_txq_try_stop(txq, bnxt_tx_avail(bp, txr),
bp->tx_wake_thresh);
@@ -1514,14 +1534,16 @@ static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
return 0;
}
-static u16 bnxt_alloc_agg_idx(struct bnxt_rx_ring_info *rxr, u16 agg_id)
+static u16 bnxt_alloc_agg_idx(struct bnxt *bp, 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;
+ u16 idx = agg_id & (bp->max_tpa_roundup_size - 1);
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)
+ idx = find_first_zero_bit(map->agg_idx_bmap,
+ bp->max_tpa_roundup_size);
+ if (idx >= bp->max_tpa_roundup_size)
return INVALID_HW_RING_ID;
}
__set_bit(idx, map->agg_idx_bmap);
@@ -1586,7 +1608,7 @@ 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);
+ agg_id = bnxt_alloc_agg_idx(bp, 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,
@@ -3584,7 +3606,7 @@ static void bnxt_free_one_tpa_info_data(struct bnxt *bp,
{
int i;
- for (i = 0; i < bp->max_tpa; i++) {
+ for (i = 0; i < bp->max_tpa_roundup_size; i++) {
struct bnxt_tpa_info *tpa_info = &rxr->rx_tpa[i];
u8 *data = tpa_info->data;
@@ -3781,7 +3803,7 @@ static void bnxt_free_one_tpa_info(struct bnxt *bp,
kfree(rxr->rx_tpa_idx_map);
rxr->rx_tpa_idx_map = NULL;
if (rxr->rx_tpa) {
- for (i = 0; i < bp->max_tpa; i++) {
+ for (i = 0; i < bp->max_tpa_roundup_size; i++) {
kfree(rxr->rx_tpa[i].agg_arr);
rxr->rx_tpa[i].agg_arr = NULL;
}
@@ -3807,13 +3829,14 @@ static int bnxt_alloc_one_tpa_info(struct bnxt *bp,
struct rx_agg_cmp *agg;
int i;
- rxr->rx_tpa = kzalloc_objs(struct bnxt_tpa_info, bp->max_tpa);
+ rxr->rx_tpa = kzalloc_objs(struct bnxt_tpa_info,
+ bp->max_tpa_roundup_size);
if (!rxr->rx_tpa)
return -ENOMEM;
if (!(bp->flags & BNXT_FLAG_CHIP_P5_PLUS))
return 0;
- for (i = 0; i < bp->max_tpa; i++) {
+ for (i = 0; i < bp->max_tpa_roundup_size; i++) {
agg = kzalloc_objs(*agg, MAX_SKB_FRAGS);
if (!agg)
return -ENOMEM;
@@ -3832,6 +3855,9 @@ static int bnxt_alloc_tpa_info(struct bnxt *bp)
bp->max_tpa = MAX_TPA;
if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
+ /* TPA is not supported at all, so there is nothing to
+ * allocate.
+ */
if (!bp->max_tpa_v2)
return 0;
bp->max_tpa = min_t(u16, bp->max_tpa_v2, MAX_TPA_P5);
@@ -3839,6 +3865,7 @@ static int bnxt_alloc_tpa_info(struct bnxt *bp)
if (bp->max_tpa <= 32 && BNXT_CHIP_P5(bp) && !BNXT_NPAR(bp))
bp->max_tpa = MAX_TPA_P5;
}
+ bp->max_tpa_roundup_size = roundup_pow_of_two(bp->max_tpa);
for (i = 0; i < bp->rx_nr_rings; i++) {
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
@@ -4551,7 +4578,7 @@ static int bnxt_alloc_one_tpa_info_data(struct bnxt *bp,
u8 *data;
int i;
- for (i = 0; i < bp->max_tpa; i++) {
+ for (i = 0; i < bp->max_tpa_roundup_size; i++) {
data = __bnxt_alloc_rx_frag(bp, &mapping, rxr,
GFP_KERNEL);
if (!data)
@@ -5006,7 +5033,8 @@ void bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
bnxt_get_max_rings(bp, &rx, &tx, true);
if (rx > 1) {
bp->flags &= ~BNXT_FLAG_NO_AGG_RINGS;
- bp->dev->hw_features |= NETIF_F_LRO;
+ if (BNXT_SUPPORTS_TPA(bp))
+ bp->dev->hw_features |= NETIF_F_LRO;
}
}
@@ -5427,6 +5455,8 @@ static void bnxt_clear_ring_indices(struct bnxt *bp)
txr->tx_prod = 0;
txr->tx_cons = 0;
txr->tx_hw_cons = 0;
+ txr->kick_pending = 0;
+ txr->kick_txbd0 = NULL;
}
rxr = bnapi->rx_ring;
@@ -11340,8 +11370,13 @@ static int bnxt_shutdown_nic(struct bnxt *bp, bool irq_re_init)
static int bnxt_init_nic(struct bnxt *bp, bool irq_re_init)
{
+ int rc;
+
bnxt_init_cp_rings(bp);
- bnxt_init_rx_rings(bp);
+ rc = bnxt_init_rx_rings(bp);
+ if (rc)
+ return rc;
+
bnxt_init_tx_rings(bp);
bnxt_init_ring_grps(bp, irq_re_init);
bnxt_init_vnics(bp);
@@ -11772,6 +11807,8 @@ static int bnxt_tx_queue_start(struct bnxt *bp, int idx)
txr->tx_prod = 0;
txr->tx_cons = 0;
txr->tx_hw_cons = 0;
+ txr->kick_pending = 0;
+ txr->kick_txbd0 = NULL;
start_tx:
WRITE_ONCE(txr->dev_state, 0);
synchronize_net();
@@ -14603,7 +14640,14 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
rxr->rx_sw_agg_prod = 0;
rxr->rx_next_cons = 0;
rxr->bnapi->in_reset = false;
- bnxt_alloc_one_rx_ring(bp, i);
+ rc = bnxt_alloc_one_rx_ring(bp, i);
+ if (rc) {
+ netdev_warn(bp->dev, "RX ring reset failed to allocate buffers, rc = %d, falling back to global reset\n",
+ rc);
+ bnxt_reset_task(bp, true);
+ bnxt_rtnl_unlock_sp(bp);
+ return;
+ }
cpr = &rxr->bnapi->cp_ring;
cpr->sw_stats->rx.rx_resets++;
if (bp->flags & BNXT_FLAG_AGG_RINGS)
@@ -16332,6 +16376,8 @@ static int bnxt_queue_mem_alloc(struct net_device *dev,
clone->need_head_pool = false;
clone->rx_page_size = qcfg->rx_page_size;
clone->rx_agg_bmap = NULL;
+ clone->rx_tpa = NULL;
+ clone->rx_tpa_idx_map = NULL;
rc = bnxt_alloc_rx_page_pool(bp, clone, rxr->page_pool->p.nid);
if (rc)
@@ -16375,11 +16421,16 @@ static int bnxt_queue_mem_alloc(struct net_device *dev,
bnxt_alloc_one_rx_ring_skb(bp, clone, idx);
if (bp->flags & BNXT_FLAG_AGG_RINGS)
bnxt_alloc_one_rx_ring_netmem(bp, clone, idx);
- if (bp->flags & BNXT_FLAG_TPA)
- bnxt_alloc_one_tpa_info_data(bp, clone);
+ if (bp->flags & BNXT_FLAG_TPA) {
+ rc = bnxt_alloc_one_tpa_info_data(bp, clone);
+ if (rc)
+ goto err_free_rx_ring_skbs;
+ }
return 0;
+err_free_rx_ring_skbs:
+ bnxt_free_one_rx_ring_skbs(bp, clone);
err_free_tpa_info:
bnxt_free_one_tpa_info(bp, clone);
err_free_rx_agg_ring:
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index ab894f8addef..c673b2ce4a0d 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -789,7 +789,6 @@ struct nqe_cn {
#define MAX_TPA 64
#define MAX_TPA_P5 256
-#define MAX_TPA_P5_MASK (MAX_TPA_P5 - 1)
#define MAX_TPA_SEGS_P5 0x3f
#if (BNXT_PAGE_SHIFT == 16)
@@ -993,6 +992,7 @@ struct bnxt_tx_ring_info {
u16 txq_index;
u8 tx_napi_idx;
u8 kick_pending;
+ struct tx_bd *kick_txbd0;
struct bnxt_db_info tx_db;
struct tx_bd *tx_desc_ring[MAX_TX_PAGES];
@@ -2380,6 +2380,7 @@ struct bnxt {
u16 max_tpa_v2;
u16 max_tpa;
+ u16 max_tpa_roundup_size;
u32 rx_buf_size;
u32 rx_buf_use_size; /* useable size */
u16 rx_offset;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c
index f7e18bea0fb8..6c1060fa2ea5 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c
@@ -31,10 +31,14 @@ static u32 bnxt_sw_gso_lhint(unsigned int len)
return TX_BD_FLAGS_LHINT_2048_AND_LARGER;
}
-netdev_tx_t bnxt_sw_udp_gso_xmit(struct bnxt *bp,
- struct bnxt_tx_ring_info *txr,
- struct netdev_queue *txq,
- struct sk_buff *skb)
+/* Transmit an skb requiring software UDP segmentation.
+ *
+ * Returns 1 if the skb was queued and new BDs were produced, 0 if the skb
+ * was dropped, or -1 if the ring is full and the skb should be retried.
+ * The caller owns the doorbell for all three cases.
+ */
+int bnxt_sw_udp_gso_xmit(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
+ struct netdev_queue *txq, struct sk_buff *skb)
{
unsigned int last_unmap_len __maybe_unused = 0;
dma_addr_t last_unmap_addr __maybe_unused = 0;
@@ -69,7 +73,7 @@ netdev_tx_t bnxt_sw_udp_gso_xmit(struct bnxt *bp,
if (unlikely(bnxt_tx_avail(bp, txr) < bds_needed)) {
netif_txq_try_stop(txq, bnxt_tx_avail(bp, txr),
bp->tx_wake_thresh);
- return NETDEV_TX_BUSY;
+ return -1;
}
/* BD backpressure alone cannot prevent overwriting in-flight
@@ -77,7 +81,7 @@ netdev_tx_t bnxt_sw_udp_gso_xmit(struct bnxt *bp,
*/
if (!netif_txq_maybe_stop(txq, bnxt_inline_avail(txr),
num_segs, num_segs))
- return NETDEV_TX_BUSY;
+ return -1;
if (unlikely(tso_dma_map_init(&map, &pdev->dev, skb, hdr_len)))
goto drop;
@@ -223,16 +227,15 @@ netdev_tx_t bnxt_sw_udp_gso_xmit(struct bnxt *bp,
netdev_tx_sent_queue(txq, skb->len);
WRITE_ONCE(txr->tx_prod, prod);
- txr->kick_pending = 1;
if (unlikely(bnxt_tx_avail(bp, txr) <= bp->tx_wake_thresh))
netif_txq_try_stop(txq, bnxt_tx_avail(bp, txr),
bp->tx_wake_thresh);
- return NETDEV_TX_OK;
+ return 1;
drop:
dev_kfree_skb_any(skb);
dev_core_stats_tx_dropped_inc(bp->dev);
- return NETDEV_TX_OK;
+ return 0;
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.h
index 47528c20f311..77d9af97cc22 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.h
@@ -38,9 +38,7 @@ static inline int bnxt_min_tx_desc_cnt(struct bnxt *bp,
return BNXT_MIN_TX_DESC_CNT;
}
-netdev_tx_t bnxt_sw_udp_gso_xmit(struct bnxt *bp,
- struct bnxt_tx_ring_info *txr,
- struct netdev_queue *txq,
- struct sk_buff *skb);
+int bnxt_sw_udp_gso_xmit(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
+ struct netdev_queue *txq, struct sk_buff *skb);
#endif
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 1e1f52285a39..d6931c41f39d 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -968,6 +968,8 @@ struct macb_dma_desc_ptp {
* of the frame
* @mapping: DMA address of the skb's fragment buffer
* @size: size of the DMA mapped buffer
+ * @fcs_len: FCS bytes appended in software, 0 or ETH_FCS_LEN, only
+ * set for the last buffer of the frame
* @mapped_as_page: true when buffer was mapped with skb_frag_dma_map(),
* false when buffer was mapped with dma_map_single()
*/
@@ -975,6 +977,7 @@ struct macb_tx_skb {
struct sk_buff *skb;
dma_addr_t mapping;
size_t size;
+ u8 fcs_len;
bool mapped_as_page;
};
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 76ee4f506033..b8234ac4b602 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -1164,6 +1164,8 @@ static int macb_mii_init(struct macb *bp)
if (err)
goto err_out_unregister_bus;
+ of_node_put(mdio_np);
+
return 0;
err_out_unregister_bus:
@@ -1322,8 +1324,8 @@ static void macb_tx_error_task(struct work_struct *work)
bp->netdev->stats.tx_packets++;
queue->stats.tx_packets++;
packets++;
- bp->netdev->stats.tx_bytes += skb->len;
- queue->stats.tx_bytes += skb->len;
+ bp->netdev->stats.tx_bytes += skb->len - tx_skb->fcs_len;
+ queue->stats.tx_bytes += skb->len - tx_skb->fcs_len;
bytes += skb->len;
}
} else {
@@ -1450,8 +1452,8 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)
skb->data);
bp->netdev->stats.tx_packets++;
queue->stats.tx_packets++;
- bp->netdev->stats.tx_bytes += skb->len;
- queue->stats.tx_bytes += skb->len;
+ bp->netdev->stats.tx_bytes += skb->len - tx_skb->fcs_len;
+ queue->stats.tx_bytes += skb->len - tx_skb->fcs_len;
packets++;
bytes += skb->len;
}
@@ -2199,7 +2201,8 @@ static void macb_poll_controller(struct net_device *netdev)
static unsigned int macb_tx_map(struct macb *bp,
struct macb_queue *queue,
struct sk_buff *skb,
- unsigned int hdrlen)
+ unsigned int hdrlen,
+ u8 fcs_len)
{
unsigned int f, nr_frags = skb_shinfo(skb)->nr_frags;
unsigned int len, i, tx_head = queue->tx_head;
@@ -2284,6 +2287,7 @@ static unsigned int macb_tx_map(struct macb *bp,
/* This is the last buffer of the frame: save socket buffer */
tx_skb->skb = skb;
+ tx_skb->fcs_len = fcs_len;
/* Update TX ring: update buffer descriptors in reverse order
* to avoid race condition
@@ -2417,6 +2421,7 @@ static inline int macb_clear_csum(struct sk_buff *skb)
return 0;
}
+/* Returns a negative errno, or the FCS bytes appended (0 or ETH_FCS_LEN). */
static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *netdev)
{
bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb) ||
@@ -2465,7 +2470,7 @@ add_fcs:
skb_put_u8(*skb, (fcs >> 16) & 0xff);
skb_put_u8(*skb, (fcs >> 24) & 0xff);
- return 0;
+ return ETH_FCS_LEN;
}
static netdev_tx_t macb_start_xmit(struct sk_buff *skb,
@@ -2478,6 +2483,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb,
netdev_tx_t ret = NETDEV_TX_OK;
unsigned int hdrlen;
unsigned long flags;
+ int fcs_len;
bool is_lso;
if (macb_clear_csum(skb)) {
@@ -2485,7 +2491,8 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb,
return ret;
}
- if (macb_pad_and_fcs(&skb, netdev)) {
+ fcs_len = macb_pad_and_fcs(&skb, netdev);
+ if (fcs_len < 0) {
dev_kfree_skb_any(skb);
return ret;
}
@@ -2548,7 +2555,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb,
}
/* Map socket buffer for DMA transfer */
- if (macb_tx_map(bp, queue, skb, hdrlen)) {
+ if (macb_tx_map(bp, queue, skb, hdrlen, fcs_len)) {
dev_kfree_skb_any(skb);
goto unlock;
}
@@ -4295,9 +4302,9 @@ static int macb_taprio_setup_replace(struct net_device *netdev,
u64 total_on_time = 0, start_time_sec = 0, start_time = conf->base_time;
u32 configured_queues = 0, speed = 0, start_time_nsec;
struct macb_queue_enst_config *enst_queue;
- struct tc_taprio_sched_entry *entry;
+ struct ethtool_link_ksettings kset = {};
struct macb *bp = netdev_priv(netdev);
- struct ethtool_link_ksettings kset;
+ struct tc_taprio_sched_entry *entry;
struct macb_queue *queue;
u32 queue_mask;
u8 queue_id;
@@ -4324,12 +4331,12 @@ static int macb_taprio_setup_replace(struct net_device *netdev,
}
speed = kset.base.speed;
- if (unlikely(speed <= 0)) {
- netdev_err(netdev, "Invalid speed: %d\n", speed);
+ if (unlikely(speed == SPEED_UNKNOWN || !speed)) {
+ netdev_err(netdev, "Invalid speed %d, link-down?\n", speed);
return -EINVAL;
}
- enst_queue = kcalloc(conf->num_entries, sizeof(*enst_queue), GFP_KERNEL);
+ enst_queue = kzalloc_objs(*enst_queue, conf->num_entries);
if (unlikely(!enst_queue))
return -ENOMEM;
@@ -5876,6 +5883,7 @@ static int macb_probe(struct platform_device *pdev)
}
spin_lock_init(&bp->lock);
spin_lock_init(&bp->stats_lock);
+ spin_lock_init(&bp->tsu_clk_lock);
/* setup capabilities */
macb_configure_caps(bp, macb_config);
@@ -5971,8 +5979,11 @@ err_out_free_tieoff:
macb_free_tieoff(bp);
err_out_unregister_mdio:
- mdiobus_unregister(bp->mii_bus);
- mdiobus_free(bp->mii_bus);
+ if (bp->mii_bus) {
+ mdiobus_unregister(bp->mii_bus);
+ mdiobus_free(bp->mii_bus);
+ }
+ phylink_destroy(bp->phylink);
err_out_phy_exit:
phy_exit(bp->phy);
@@ -6001,8 +6012,10 @@ static void macb_remove(struct platform_device *pdev)
unregister_netdev(netdev);
macb_free_tieoff(bp);
phy_exit(bp->phy);
- mdiobus_unregister(bp->mii_bus);
- mdiobus_free(bp->mii_bus);
+ if (bp->mii_bus) {
+ mdiobus_unregister(bp->mii_bus);
+ mdiobus_free(bp->mii_bus);
+ }
device_set_wakeup_enable(&bp->pdev->dev, 0);
cancel_delayed_work_sync(&bp->tx_lpi_work);
diff --git a/drivers/net/ethernet/cadence/macb_ptp.c b/drivers/net/ethernet/cadence/macb_ptp.c
index e5195d7dac1d..6d9166389988 100644
--- a/drivers/net/ethernet/cadence/macb_ptp.c
+++ b/drivers/net/ethernet/cadence/macb_ptp.c
@@ -334,6 +334,7 @@ void gem_ptp_init(struct net_device *netdev)
bp->tsu_rate = bp->ptp_info->get_tsu_rate(bp);
bp->ptp_clock_info.max_adj = bp->ptp_info->get_ptp_max_adj();
gem_ptp_init_timer(bp);
+ gem_ptp_init_tsu(bp);
bp->ptp_clock = ptp_clock_register(&bp->ptp_clock_info, &netdev->dev);
if (IS_ERR(bp->ptp_clock)) {
pr_err("ptp clock register failed: %ld\n",
@@ -345,10 +346,6 @@ void gem_ptp_init(struct net_device *netdev)
return;
}
- spin_lock_init(&bp->tsu_clk_lock);
-
- gem_ptp_init_tsu(bp);
-
dev_info(&bp->pdev->dev, "%s ptp clock registered.\n",
GEM_PTP_TIMER_NAME);
}
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index 4a67947cfb9f..7a509a056990 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -137,6 +137,12 @@ struct enic_port_profile {
u8 mac_addr[ETH_ALEN];
};
+enum enic_vf_link_state {
+ ENIC_VF_LINK_STATE_UNKNOWN,
+ ENIC_VF_LINK_STATE_DOWN,
+ ENIC_VF_LINK_STATE_UP,
+};
+
/* enic_rfs_fltr_node - rfs filter node in hash table
* @@keys: IPv4 5 tuple
* @flow_id: flow_id of clsf filter provided by kernel
@@ -312,19 +318,25 @@ struct enic {
unsigned int admin_msg_count; /* current depth of admin_msg_list */
void (*admin_rq_handler)(struct enic *enic, void *buf,
unsigned int len);
+ /* The PF is authoritative for a V2 VF's carrier. Keep the last
+ * notification across an ordinary netdev close/open and serialize it
+ * against the open/stop carrier transition.
+ */
+ spinlock_t vf_link_state_lock;
+ enum enic_vf_link_state vf_link_state;
+ bool vf_link_running;
/* MBOX protocol state — mbox_lock serializes admin WQ sends */
struct mutex mbox_lock;
u64 mbox_msg_num;
- /* MBOX request-reply state. mbox_expected_reply is written and
- * cleared by the process-context request helpers (capability/register/
- * unregister) and only read by the admin_msg_work receive handlers, so
- * it is annotated with READ_ONCE()/WRITE_ONCE() rather than locked:
- * only one request is in flight at a time (requesters run under RTNL or
- * single-threaded probe/remove), so each request is serialized and its
- * reply completes mbox_comp before the next request is issued.
+ /* MBOX request-reply state. Existing request callers allow only one
+ * request in flight. The state lock arbitrates reply acceptance against
+ * timeout invalidation, while mbox_comp publishes the accepted result to
+ * the requester.
*/
struct completion mbox_comp;
+ spinlock_t mbox_state_lock; /* protects expected reply state */
+ u64 mbox_expected_msg_num;
u8 mbox_expected_reply;
bool mbox_initialized;
diff --git a/drivers/net/ethernet/cisco/enic/enic_admin.c b/drivers/net/ethernet/cisco/enic/enic_admin.c
index 7188f1b81c04..61c82b48044d 100644
--- a/drivers/net/ethernet/cisco/enic/enic_admin.c
+++ b/drivers/net/ethernet/cisco/enic/enic_admin.c
@@ -137,7 +137,7 @@ static void enic_admin_msg_enqueue(struct enic *enic, void *buf,
{
struct enic_admin_msg *msg;
- msg = kmalloc(struct_size(msg, data, len), GFP_KERNEL);
+ msg = kmalloc_flex(*msg, data, len);
if (!msg)
return;
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 0baef7a120ec..6b5824f45a14 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1800,6 +1800,8 @@ static int enic_open(struct net_device *netdev)
enic_notify_timer_start(enic);
enic_rfs_timer_start(enic);
+ if (enic_is_sriov_vf_v2(enic))
+ enic_mbox_vf_link_state_set_running(enic, true);
return 0;
@@ -1853,7 +1855,10 @@ static int enic_stop(struct net_device *netdev)
for (i = 0; i < enic->rq_count; i++)
napi_disable(&enic->napi[i]);
- netif_carrier_off(netdev);
+ if (enic_is_sriov_vf_v2(enic))
+ enic_mbox_vf_link_state_set_running(enic, false);
+ else
+ netif_carrier_off(netdev);
if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
for (i = 0; i < enic->wq_count; i++)
napi_disable(&enic->napi[enic_cq_wq(enic, i)]);
@@ -2201,9 +2206,10 @@ static void enic_admin_chan_reopen(struct enic *enic)
{
int err;
- /* Install the MBOX receive handler and reset the sequence number
- * before opening the channel, so the handler is in place before the
- * admin interrupt is unmasked and no early completion is dropped.
+ /* Install the MBOX receive handler and clear pending reply state before
+ * opening the channel, so the handler is in place before the admin
+ * interrupt is unmasked and no early completion is dropped. Keep the
+ * sequence number monotonic across channel generations.
*/
enic_mbox_init(enic);
@@ -2215,7 +2221,7 @@ static void enic_admin_chan_reopen(struct enic *enic)
* registration over a dead channel.
*/
if (enic_is_sriov_vf_v2(enic))
- enic->vf_registered = false;
+ WRITE_ONCE(enic->vf_registered, false);
err = enic_admin_channel_open(enic);
if (err) {
@@ -2271,6 +2277,8 @@ static void enic_reset(struct work_struct *work)
enic_admin_channel_close(enic);
enic_stop(enic->netdev);
+ if (enic_is_sriov_vf_v2(enic))
+ enic_mbox_vf_link_state_reset(enic);
enic_dev_soft_reset(enic);
enic_reset_addr_lists(enic);
@@ -2315,6 +2323,8 @@ static void enic_tx_hang_reset(struct work_struct *work)
enic_dev_hang_notify(enic);
enic_stop(enic->netdev);
+ if (enic_is_sriov_vf_v2(enic))
+ enic_mbox_vf_link_state_reset(enic);
enic_dev_hang_reset(enic);
enic_reset_addr_lists(enic);
@@ -2858,7 +2868,7 @@ enic_sriov_v2_enable(struct enic *enic, int num_vfs)
return -EOPNOTSUPP;
}
- enic->vf_state = kcalloc(num_vfs, sizeof(*enic->vf_state), GFP_KERNEL);
+ enic->vf_state = kzalloc_objs(*enic->vf_state, num_vfs);
if (!enic->vf_state)
return -ENOMEM;
@@ -2946,7 +2956,7 @@ enic_sriov_configure(struct pci_dev *pdev, int num_vfs)
if (enic->vf_type == ENIC_VF_TYPE_V2)
return enic_sriov_v2_enable(enic, num_vfs);
- pp = kcalloc(num_vfs, sizeof(*pp), GFP_KERNEL);
+ pp = kzalloc_objs(*pp, num_vfs);
if (!pp)
return -ENOMEM;
@@ -2971,7 +2981,7 @@ enic_sriov_configure(struct pci_dev *pdev, int num_vfs)
return 0;
}
- pp = kzalloc_obj(*enic->pp, GFP_KERNEL);
+ pp = kzalloc_obj(*enic->pp);
if (!pp)
return -ENOMEM;
@@ -3015,6 +3025,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
enic = netdev_priv(netdev);
enic->netdev = netdev;
enic->pdev = pdev;
+ spin_lock_init(&enic->vf_link_state_lock);
/* Setup PCI resources
*/
@@ -3339,7 +3350,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_admin_close:
if (enic_is_sriov_vf_v2(enic)) {
- if (enic->vf_registered) {
+ if (READ_ONCE(enic->vf_registered)) {
int unreg_err = enic_mbox_vf_unregister(enic);
if (unreg_err)
@@ -3392,7 +3403,7 @@ static void enic_remove(struct pci_dev *pdev)
* touching a netdev that is being torn down.
*/
if (enic_is_sriov_vf_v2(enic)) {
- if (enic->vf_registered) {
+ if (READ_ONCE(enic->vf_registered)) {
int unreg_err = enic_mbox_vf_unregister(enic);
if (unreg_err)
diff --git a/drivers/net/ethernet/cisco/enic/enic_mbox.c b/drivers/net/ethernet/cisco/enic/enic_mbox.c
index 2fb0f1e2ff50..5c93ca49552a 100644
--- a/drivers/net/ethernet/cisco/enic/enic_mbox.c
+++ b/drivers/net/ethernet/cisco/enic/enic_mbox.c
@@ -18,22 +18,25 @@
#define ENIC_MBOX_POLL_TIMEOUT_US 5000000
#define ENIC_MBOX_POLL_INTERVAL_US 100
-static void enic_mbox_fill_hdr(struct enic *enic, struct enic_mbox_hdr *hdr,
- u8 msg_type, u16 dst_vnic_id, u16 msg_len)
+static void enic_mbox_fill_hdr(struct enic_mbox_hdr *hdr, u8 msg_type,
+ u16 dst_vnic_id, u16 msg_len, u64 msg_num)
{
memset(hdr, 0, sizeof(*hdr));
hdr->dst_vnic_id = cpu_to_le16(dst_vnic_id);
hdr->msg_type = msg_type;
hdr->msg_len = cpu_to_le16(msg_len);
- hdr->msg_num = cpu_to_le64(++enic->mbox_msg_num);
+ hdr->msg_num = cpu_to_le64(msg_num);
}
-int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id,
- void *payload, u16 payload_len)
+static int enic_mbox_send_msg_id(struct enic *enic, u8 msg_type,
+ u16 dst_vnic_id, void *payload,
+ u16 payload_len, u64 msg_num, bool reuse_msg_num,
+ u8 expected_reply)
{
size_t total_len = sizeof(struct enic_mbox_hdr) + payload_len;
struct vnic_wq *wq = &enic->admin_wq;
struct wq_enet_desc *desc;
+ bool reply_expected = false;
unsigned long timeout;
dma_addr_t dma_addr;
u16 vlan_tag;
@@ -68,7 +71,21 @@ int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id,
goto unlock;
}
- enic_mbox_fill_hdr(enic, buf, msg_type, dst_vnic_id, total_len);
+ /* Replies reuse the initiating message number. Requests and
+ * notifications allocate a new one.
+ */
+ if (!reuse_msg_num)
+ msg_num = ++enic->mbox_msg_num;
+ if (expected_reply) {
+ reinit_completion(&enic->mbox_comp);
+ spin_lock_bh(&enic->mbox_state_lock);
+ enic->mbox_expected_reply = expected_reply;
+ enic->mbox_expected_msg_num = msg_num;
+ spin_unlock_bh(&enic->mbox_state_lock);
+ reply_expected = true;
+ }
+
+ enic_mbox_fill_hdr(buf, msg_type, dst_vnic_id, total_len, msg_num);
if (payload_len) {
void *dst = buf + sizeof(struct enic_mbox_hdr);
@@ -139,18 +156,66 @@ int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id,
"MBOX send msg_type %u dst %u vlan %u err %d\n",
msg_type, dst_vnic_id, vlan_tag, err);
unlock:
+ if (err && reply_expected) {
+ spin_lock_bh(&enic->mbox_state_lock);
+ if (enic->mbox_expected_reply == expected_reply &&
+ enic->mbox_expected_msg_num == msg_num) {
+ enic->mbox_expected_reply = 0;
+ enic->mbox_expected_msg_num = 0;
+ }
+ spin_unlock_bh(&enic->mbox_state_lock);
+ }
mutex_unlock(&enic->mbox_lock);
return err;
}
+int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id,
+ void *payload, u16 payload_len)
+{
+ return enic_mbox_send_msg_id(enic, msg_type, dst_vnic_id, payload,
+ payload_len, 0, false, 0);
+}
+
+static int enic_mbox_send_reply(struct enic *enic, u8 msg_type,
+ u16 dst_vnic_id, void *payload, u16 payload_len,
+ u64 msg_num)
+{
+ return enic_mbox_send_msg_id(enic, msg_type, dst_vnic_id, payload,
+ payload_len, msg_num, true, 0);
+}
+
+static int enic_mbox_vf_send_request(struct enic *enic, u8 request_type,
+ u8 expected_reply, void *payload,
+ u16 payload_len)
+{
+ return enic_mbox_send_msg_id(enic, request_type, ENIC_MBOX_DST_PF,
+ payload, payload_len, 0, false,
+ expected_reply);
+}
+
static int enic_mbox_wait_reply(struct enic *enic, unsigned long timeout_ms)
{
unsigned long left;
+ int err = 0;
left = wait_for_completion_timeout(&enic->mbox_comp,
msecs_to_jiffies(timeout_ms));
+ if (left)
+ return 0;
+
+ /* Invalidate a request that the handler has not already accepted. A
+ * delayed reply cannot match a later request because message numbers are
+ * monotonic across channel reopen.
+ */
+ spin_lock_bh(&enic->mbox_state_lock);
+ if (enic->mbox_expected_reply) {
+ enic->mbox_expected_reply = 0;
+ enic->mbox_expected_msg_num = 0;
+ err = -ETIMEDOUT;
+ }
+ spin_unlock_bh(&enic->mbox_state_lock);
- return left ? 0 : -ETIMEDOUT;
+ return err;
}
int enic_mbox_send_link_state(struct enic *enic, u16 vf_id, u32 link_state)
@@ -178,8 +243,8 @@ static int enic_mbox_pf_handle_capability(struct enic *enic, void *msg,
reply.reply.ret_major = cpu_to_le16(0);
reply.version = cpu_to_le32(ENIC_MBOX_CAP_VERSION_1);
- return enic_mbox_send_msg(enic, ENIC_MBOX_VF_CAPABILITY_REPLY, vf_id,
- &reply, sizeof(reply));
+ return enic_mbox_send_reply(enic, ENIC_MBOX_VF_CAPABILITY_REPLY, vf_id,
+ &reply, sizeof(reply), msg_num);
}
static int enic_mbox_pf_handle_register(struct enic *enic, void *msg,
@@ -208,8 +273,8 @@ static int enic_mbox_pf_handle_register(struct enic *enic, void *msg,
}
reply.reply.ret_major = cpu_to_le16(0);
- err = enic_mbox_send_msg(enic, ENIC_MBOX_VF_REGISTER_REPLY, vf_id,
- &reply, sizeof(reply));
+ err = enic_mbox_send_reply(enic, ENIC_MBOX_VF_REGISTER_REPLY, vf_id,
+ &reply, sizeof(reply), msg_num);
if (err)
return err;
@@ -253,8 +318,8 @@ static int enic_mbox_pf_handle_unregister(struct enic *enic, void *msg,
enic->vf_state[vf_id].registered = false;
reply.reply.ret_major = cpu_to_le16(0);
- err = enic_mbox_send_msg(enic, ENIC_MBOX_VF_UNREGISTER_REPLY, vf_id,
- &reply, sizeof(reply));
+ err = enic_mbox_send_reply(enic, ENIC_MBOX_VF_UNREGISTER_REPLY, vf_id,
+ &reply, sizeof(reply), msg_num);
if (net_ratelimit())
netdev_info(enic->netdev,
@@ -324,105 +389,116 @@ static void enic_mbox_pf_process_msg(struct enic *enic,
hdr->msg_type, vf_id, err);
}
-static void enic_mbox_vf_handle_capability_reply(struct enic *enic,
- void *payload)
+static void enic_mbox_vf_handle_reply(struct enic *enic, u8 reply_type,
+ void *payload, u64 msg_num)
{
- struct enic_mbox_vf_capability_reply_msg *reply = payload;
-
- if (READ_ONCE(enic->mbox_expected_reply) != ENIC_MBOX_VF_CAPABILITY_REPLY) {
+ struct enic_mbox_generic_reply *reply = payload;
+ u16 ret_major = le16_to_cpu(reply->ret_major);
+ u64 expected_msg_num;
+ u8 expected_type;
+
+ spin_lock_bh(&enic->mbox_state_lock);
+ expected_type = enic->mbox_expected_reply;
+ expected_msg_num = enic->mbox_expected_msg_num;
+ if (expected_type != reply_type || expected_msg_num != msg_num) {
+ spin_unlock_bh(&enic->mbox_state_lock);
netdev_warn(enic->netdev,
- "MBOX: stale capability reply (expected %u), drop\n",
- READ_ONCE(enic->mbox_expected_reply));
+ "MBOX: stale reply %u/%llu (expected %u/%llu), drop\n",
+ reply_type, (unsigned long long)msg_num,
+ expected_type, (unsigned long long)expected_msg_num);
return;
}
- if (le16_to_cpu(reply->reply.ret_major) == 0)
- enic->pf_cap_version = le32_to_cpu(reply->version);
- else
- netdev_warn(enic->netdev,
- "MBOX: PF rejected capability request: %u/%u\n",
- le16_to_cpu(reply->reply.ret_major),
- le16_to_cpu(reply->reply.ret_minor));
- complete(&enic->mbox_comp);
-}
+ if (!ret_major) {
+ switch (reply_type) {
+ case ENIC_MBOX_VF_CAPABILITY_REPLY: {
+ struct enic_mbox_vf_capability_reply_msg *cap = payload;
-static void enic_mbox_vf_handle_register_reply(struct enic *enic,
- void *payload)
-{
- struct enic_mbox_vf_register_reply_msg *reply = payload;
-
- if (READ_ONCE(enic->mbox_expected_reply) != ENIC_MBOX_VF_REGISTER_REPLY) {
- netdev_warn(enic->netdev,
- "MBOX: stale register reply (expected %u), drop\n",
- READ_ONCE(enic->mbox_expected_reply));
- return;
- }
-
- if (le16_to_cpu(reply->reply.ret_major)) {
- netdev_warn(enic->netdev,
- "MBOX: VF register rejected by PF: %u/%u\n",
- le16_to_cpu(reply->reply.ret_major),
- le16_to_cpu(reply->reply.ret_minor));
- } else {
- enic->vf_registered = true;
+ WRITE_ONCE(enic->pf_cap_version,
+ le32_to_cpu(cap->version));
+ break;
+ }
+ case ENIC_MBOX_VF_REGISTER_REPLY:
+ WRITE_ONCE(enic->vf_registered, true);
+ break;
+ case ENIC_MBOX_VF_UNREGISTER_REPLY:
+ WRITE_ONCE(enic->vf_registered, false);
+ break;
+ }
}
+ enic->mbox_expected_reply = 0;
+ enic->mbox_expected_msg_num = 0;
complete(&enic->mbox_comp);
-}
+ spin_unlock_bh(&enic->mbox_state_lock);
-static void enic_mbox_vf_handle_unregister_reply(struct enic *enic,
- void *payload)
-{
- struct enic_mbox_vf_register_reply_msg *reply = payload;
-
- if (READ_ONCE(enic->mbox_expected_reply) != ENIC_MBOX_VF_UNREGISTER_REPLY) {
+ if (ret_major)
netdev_warn(enic->netdev,
- "MBOX: stale unregister reply (expected %u), drop\n",
- READ_ONCE(enic->mbox_expected_reply));
- return;
- }
-
- if (le16_to_cpu(reply->reply.ret_major)) {
- netdev_warn(enic->netdev,
- "MBOX: VF unregister rejected by PF: %u/%u\n",
- le16_to_cpu(reply->reply.ret_major),
- le16_to_cpu(reply->reply.ret_minor));
- } else {
- enic->vf_registered = false;
- }
- complete(&enic->mbox_comp);
+ "MBOX: PF rejected reply type %u: %u/%u\n",
+ reply_type, ret_major,
+ le16_to_cpu(reply->ret_minor));
}
-static void enic_mbox_vf_handle_link_state(struct enic *enic, void *payload)
+static void enic_mbox_vf_handle_link_state(struct enic *enic, void *payload,
+ u64 msg_num)
{
struct enic_mbox_pf_link_state_notif_msg *notif = payload;
struct enic_mbox_pf_link_state_ack_msg ack = {};
+ u32 link_state = le32_to_cpu(notif->link_state);
int err;
- switch (le32_to_cpu(notif->link_state)) {
+ spin_lock_bh(&enic->vf_link_state_lock);
+ switch (link_state) {
case ENIC_MBOX_LINK_STATE_ENABLE:
- if (!netif_carrier_ok(enic->netdev))
+ enic->vf_link_state = ENIC_VF_LINK_STATE_UP;
+ if (enic->vf_link_running &&
+ !netif_carrier_ok(enic->netdev))
netif_carrier_on(enic->netdev);
netdev_dbg(enic->netdev, "MBOX: link state -> UP\n");
break;
case ENIC_MBOX_LINK_STATE_DISABLE:
- if (netif_carrier_ok(enic->netdev))
+ enic->vf_link_state = ENIC_VF_LINK_STATE_DOWN;
+ if (enic->vf_link_running &&
+ netif_carrier_ok(enic->netdev))
netif_carrier_off(enic->netdev);
netdev_dbg(enic->netdev, "MBOX: link state -> DOWN\n");
break;
default:
netdev_warn(enic->netdev, "MBOX: unknown link state %u\n",
- le32_to_cpu(notif->link_state));
+ link_state);
ack.ack.ret_major = cpu_to_le16(ENIC_MBOX_ERR_GENERIC);
break;
}
+ spin_unlock_bh(&enic->vf_link_state_lock);
- err = enic_mbox_send_msg(enic, ENIC_MBOX_PF_LINK_STATE_ACK,
- ENIC_MBOX_DST_PF, &ack, sizeof(ack));
+ err = enic_mbox_send_reply(enic, ENIC_MBOX_PF_LINK_STATE_ACK,
+ ENIC_MBOX_DST_PF, &ack, sizeof(ack), msg_num);
if (err && net_ratelimit())
netdev_warn(enic->netdev,
"MBOX: failed to send link state ACK: %d\n", err);
}
+void enic_mbox_vf_link_state_reset(struct enic *enic)
+{
+ spin_lock_bh(&enic->vf_link_state_lock);
+ enic->vf_link_state = ENIC_VF_LINK_STATE_UNKNOWN;
+ if (enic->vf_link_running && netif_carrier_ok(enic->netdev))
+ netif_carrier_off(enic->netdev);
+ spin_unlock_bh(&enic->vf_link_state_lock);
+}
+
+void enic_mbox_vf_link_state_set_running(struct enic *enic, bool running)
+{
+ spin_lock_bh(&enic->vf_link_state_lock);
+ enic->vf_link_running = running;
+ if (running && enic->vf_link_state == ENIC_VF_LINK_STATE_UP) {
+ if (!netif_carrier_ok(enic->netdev))
+ netif_carrier_on(enic->netdev);
+ } else if (netif_carrier_ok(enic->netdev)) {
+ netif_carrier_off(enic->netdev);
+ }
+ spin_unlock_bh(&enic->vf_link_state_lock);
+}
+
static bool enic_mbox_vf_payload_ok(struct enic *enic, u8 msg_type,
u16 payload_len, size_t min_len)
{
@@ -439,6 +515,8 @@ static void enic_mbox_vf_process_msg(struct enic *enic,
struct enic_mbox_hdr *hdr, void *payload,
u16 payload_len)
{
+ u64 msg_num = le64_to_cpu(hdr->msg_num);
+
switch (hdr->msg_type) {
case ENIC_MBOX_VF_CAPABILITY_REPLY: {
size_t exp = sizeof(struct enic_mbox_vf_capability_reply_msg);
@@ -446,7 +524,7 @@ static void enic_mbox_vf_process_msg(struct enic *enic,
if (!enic_mbox_vf_payload_ok(enic, hdr->msg_type,
payload_len, exp))
return;
- enic_mbox_vf_handle_capability_reply(enic, payload);
+ enic_mbox_vf_handle_reply(enic, hdr->msg_type, payload, msg_num);
break;
}
case ENIC_MBOX_VF_REGISTER_REPLY: {
@@ -455,7 +533,7 @@ static void enic_mbox_vf_process_msg(struct enic *enic,
if (!enic_mbox_vf_payload_ok(enic, hdr->msg_type,
payload_len, exp))
return;
- enic_mbox_vf_handle_register_reply(enic, payload);
+ enic_mbox_vf_handle_reply(enic, hdr->msg_type, payload, msg_num);
break;
}
case ENIC_MBOX_VF_UNREGISTER_REPLY: {
@@ -464,7 +542,7 @@ static void enic_mbox_vf_process_msg(struct enic *enic,
if (!enic_mbox_vf_payload_ok(enic, hdr->msg_type,
payload_len, exp))
return;
- enic_mbox_vf_handle_unregister_reply(enic, payload);
+ enic_mbox_vf_handle_reply(enic, hdr->msg_type, payload, msg_num);
break;
}
case ENIC_MBOX_PF_LINK_STATE_NOTIF: {
@@ -473,7 +551,7 @@ static void enic_mbox_vf_process_msg(struct enic *enic,
if (!enic_mbox_vf_payload_ok(enic, hdr->msg_type,
payload_len, exp))
return;
- enic_mbox_vf_handle_link_state(enic, payload);
+ enic_mbox_vf_handle_link_state(enic, payload, msg_num);
break;
}
default:
@@ -542,32 +620,31 @@ static void enic_mbox_recv_handler(struct enic *enic, void *buf,
int enic_mbox_vf_capability_check(struct enic *enic)
{
struct enic_mbox_vf_capability_msg req = {};
+ u32 version;
int err;
- enic->pf_cap_version = 0;
- reinit_completion(&enic->mbox_comp);
- WRITE_ONCE(enic->mbox_expected_reply, ENIC_MBOX_VF_CAPABILITY_REPLY);
+ WRITE_ONCE(enic->pf_cap_version, 0);
req.version = cpu_to_le32(ENIC_MBOX_CAP_VERSION_1);
- err = enic_mbox_send_msg(enic, ENIC_MBOX_VF_CAPABILITY_REQUEST,
- ENIC_MBOX_DST_PF, &req, sizeof(req));
- if (err) {
- WRITE_ONCE(enic->mbox_expected_reply, 0);
+ err = enic_mbox_vf_send_request(enic,
+ ENIC_MBOX_VF_CAPABILITY_REQUEST,
+ ENIC_MBOX_VF_CAPABILITY_REPLY,
+ &req, sizeof(req));
+ if (err)
return err;
- }
err = enic_mbox_wait_reply(enic, 3000);
- WRITE_ONCE(enic->mbox_expected_reply, 0);
+ version = READ_ONCE(enic->pf_cap_version);
if (err) {
netdev_warn(enic->netdev,
"MBOX: no capability reply from PF\n");
return err;
}
- if (enic->pf_cap_version < ENIC_MBOX_CAP_VERSION_1) {
+ if (version < ENIC_MBOX_CAP_VERSION_1) {
netdev_warn(enic->netdev,
"MBOX: PF rejected capability request or reported unsupported version %u\n",
- enic->pf_cap_version);
+ version);
return -EOPNOTSUPP;
}
@@ -576,28 +653,25 @@ int enic_mbox_vf_capability_check(struct enic *enic)
int enic_mbox_vf_register(struct enic *enic)
{
+ bool registered;
int err;
- enic->vf_registered = false;
- reinit_completion(&enic->mbox_comp);
- WRITE_ONCE(enic->mbox_expected_reply, ENIC_MBOX_VF_REGISTER_REPLY);
+ WRITE_ONCE(enic->vf_registered, false);
- err = enic_mbox_send_msg(enic, ENIC_MBOX_VF_REGISTER_REQUEST,
- ENIC_MBOX_DST_PF, NULL, 0);
- if (err) {
- WRITE_ONCE(enic->mbox_expected_reply, 0);
+ err = enic_mbox_vf_send_request(enic, ENIC_MBOX_VF_REGISTER_REQUEST,
+ ENIC_MBOX_VF_REGISTER_REPLY, NULL, 0);
+ if (err)
return err;
- }
err = enic_mbox_wait_reply(enic, 3000);
- WRITE_ONCE(enic->mbox_expected_reply, 0);
+ registered = READ_ONCE(enic->vf_registered);
if (err) {
netdev_warn(enic->netdev,
"MBOX: VF registration with PF timed out\n");
return err;
}
- if (!enic->vf_registered)
+ if (!registered)
return -ENODEV;
return 0;
@@ -605,43 +679,48 @@ int enic_mbox_vf_register(struct enic *enic)
int enic_mbox_vf_unregister(struct enic *enic)
{
+ bool registered;
int err;
- if (!enic->vf_registered)
+ if (!READ_ONCE(enic->vf_registered))
return 0;
- reinit_completion(&enic->mbox_comp);
- WRITE_ONCE(enic->mbox_expected_reply, ENIC_MBOX_VF_UNREGISTER_REPLY);
-
- err = enic_mbox_send_msg(enic, ENIC_MBOX_VF_UNREGISTER_REQUEST,
- ENIC_MBOX_DST_PF, NULL, 0);
- if (err) {
- WRITE_ONCE(enic->mbox_expected_reply, 0);
+ err = enic_mbox_vf_send_request(enic,
+ ENIC_MBOX_VF_UNREGISTER_REQUEST,
+ ENIC_MBOX_VF_UNREGISTER_REPLY,
+ NULL, 0);
+ if (err)
return err;
- }
err = enic_mbox_wait_reply(enic, 3000);
- WRITE_ONCE(enic->mbox_expected_reply, 0);
+ registered = READ_ONCE(enic->vf_registered);
if (err)
return err;
- if (enic->vf_registered)
+ if (registered)
return -EACCES;
return 0;
}
void enic_mbox_init(struct enic *enic)
{
- /* mbox_lock and mbox_comp must be initialized exactly once per
+ bool reinit = enic->mbox_initialized;
+
+ /* MBOX locks and mbox_comp must be initialized exactly once per
* device lifetime; the PF sriov_configure path can re-enter this
* on each enable cycle where these primitives are already set up.
*/
- if (!enic->mbox_initialized) {
+ if (!reinit) {
mutex_init(&enic->mbox_lock);
init_completion(&enic->mbox_comp);
+ spin_lock_init(&enic->mbox_state_lock);
+ enic->mbox_msg_num = 0;
enic->mbox_initialized = true;
} else {
reinit_completion(&enic->mbox_comp);
}
- enic->mbox_msg_num = 0;
+ spin_lock_bh(&enic->mbox_state_lock);
+ enic->mbox_expected_reply = 0;
+ enic->mbox_expected_msg_num = 0;
+ spin_unlock_bh(&enic->mbox_state_lock);
enic->admin_rq_handler = enic_mbox_recv_handler;
}
diff --git a/drivers/net/ethernet/cisco/enic/enic_mbox.h b/drivers/net/ethernet/cisco/enic/enic_mbox.h
index 15e30ee2b0ed..60409bad2f28 100644
--- a/drivers/net/ethernet/cisco/enic/enic_mbox.h
+++ b/drivers/net/ethernet/cisco/enic/enic_mbox.h
@@ -88,6 +88,8 @@ void enic_mbox_init(struct enic *enic);
int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id,
void *payload, u16 payload_len);
int enic_mbox_send_link_state(struct enic *enic, u16 vf_id, u32 link_state);
+void enic_mbox_vf_link_state_reset(struct enic *enic);
+void enic_mbox_vf_link_state_set_running(struct enic *enic, bool running);
int enic_mbox_vf_capability_check(struct enic *enic);
int enic_mbox_vf_register(struct enic *enic);
int enic_mbox_vf_unregister(struct enic *enic);
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 4c762229ce42..f08de623e6f7 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -124,6 +124,7 @@ struct gemini_ethernet_port {
unsigned int rx_coalesce_nsecs;
struct sk_buff *rx_skb;
unsigned int rx_frag_nr;
+ bool rx_dropping;
unsigned int freeq_refill;
struct gmac_txq txq[TX_QUEUE_NUM];
@@ -1439,7 +1440,8 @@ update_exit:
return skb;
}
-static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
+static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget,
+ unsigned int *freeq_consumed)
{
struct gemini_ethernet_port *port = netdev_priv(netdev);
unsigned short m = (1 << port->rxq_order) - 1;
@@ -1447,9 +1449,12 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
void __iomem *ptr_reg = port->rxq_rwptr;
unsigned int frag_nr = port->rx_frag_nr;
struct sk_buff *skb = port->rx_skb;
+ unsigned int consumed = 0;
unsigned int frame_len, frag_len;
struct gmac_rxdesc *rx = NULL;
struct gmac_queue_page *gpage;
+ unsigned int received = 0;
+ bool dropping = port->rx_dropping;
union gmac_rxdesc_0 word0;
union gmac_rxdesc_1 word1;
union gmac_rxdesc_3 word3;
@@ -1471,6 +1476,7 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
w = rw.bits.wptr;
while (budget && w != r) {
+ page = NULL;
rx = port->rxq_ring + r;
word0 = rx->word0;
word1 = rx->word1;
@@ -1479,11 +1485,22 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
r++;
r &= m;
+ consumed++;
frag_len = word0.bits.buffer_size;
frame_len = word1.bits.byte_count;
page_offs = mapping & ~PAGE_MASK;
+ if (word3.bits32 & SOF_BIT) {
+ if (skb) {
+ napi_free_frags(&port->napi);
+ port->stats.rx_dropped++;
+ skb = NULL;
+ frag_nr = 0;
+ }
+ dropping = false;
+ }
+
if (!mapping) {
netdev_err(netdev,
"rxq[%u]: HW BUG: zero DMA desc\n", r);
@@ -1494,24 +1511,11 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
gpage = gmac_get_queue_page(geth, port, mapping + PAGE_SIZE);
if (!gpage) {
dev_err(geth->dev, "could not find mapping\n");
- port->stats.rx_dropped++;
- if (skb) {
- napi_free_frags(&port->napi);
- skb = NULL;
- frag_nr = 0;
- }
- continue;
+ goto err_drop;
}
page = gpage->page;
if (word3.bits32 & SOF_BIT) {
- if (skb) {
- napi_free_frags(&port->napi);
- port->stats.rx_dropped++;
- skb = NULL;
- frag_nr = 0;
- }
-
skb = gmac_skb_if_good_frame(port, word0, frame_len);
if (!skb)
goto err_drop;
@@ -1521,8 +1525,7 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
frag_nr = 0;
} else if (!skb) {
- put_page(page);
- continue;
+ goto err_drop;
}
if (word3.bits32 & EOF_BIT)
@@ -1545,9 +1548,8 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
napi_gro_frags(&port->napi);
skb = NULL;
frag_nr = 0;
- --budget;
}
- continue;
+ goto next_desc;
err_drop:
if (skb) {
@@ -1556,16 +1558,29 @@ err_drop:
frag_nr = 0;
}
- if (mapping)
+ if (page)
put_page(page);
- port->stats.rx_dropped++;
+ if (!dropping) {
+ port->stats.rx_dropped++;
+ dropping = true;
+ }
+
+next_desc:
+ /* Final or single-descriptor fragment, advance things */
+ if (word3.bits32 & EOF_BIT) {
+ budget--;
+ received++;
+ dropping = false;
+ }
}
port->rx_skb = skb;
port->rx_frag_nr = frag_nr;
+ port->rx_dropping = dropping;
+ *freeq_consumed = consumed;
writew(r, ptr_reg);
- return budget;
+ return received;
}
static int gmac_napi_poll(struct napi_struct *napi, int budget)
@@ -1573,26 +1588,27 @@ static int gmac_napi_poll(struct napi_struct *napi, int budget)
struct gemini_ethernet_port *port = netdev_priv(napi->dev);
struct gemini_ethernet *geth = port->geth;
unsigned int freeq_threshold;
+ unsigned int freeq_consumed;
unsigned int received;
freeq_threshold = 1 << (geth->freeq_order - 1);
u64_stats_update_begin(&port->rx_stats_syncp);
- received = gmac_rx(napi->dev, budget);
- if (received < budget) {
- napi_gro_flush(napi, false);
- napi_complete_done(napi, received);
- gmac_enable_rx_irq(napi->dev, 1);
+ received = gmac_rx(napi->dev, budget, &freeq_consumed);
+ if (received < budget)
++port->rx_napi_exits;
- }
- port->freeq_refill += (budget - received);
+ u64_stats_update_end(&port->rx_stats_syncp);
+
+ port->freeq_refill += freeq_consumed;
if (port->freeq_refill > freeq_threshold) {
port->freeq_refill -= freeq_threshold;
geth_fill_freeq(geth, true);
}
- u64_stats_update_end(&port->rx_stats_syncp);
+ if (received < budget && napi_complete_done(napi, received))
+ gmac_enable_rx_irq(napi->dev, 1);
+
return received;
}
@@ -1893,6 +1909,7 @@ static int gmac_stop(struct net_device *netdev)
napi_disable(&port->napi);
port->rx_skb = NULL;
port->rx_frag_nr = 0;
+ port->rx_dropping = false;
gmac_enable_irq(netdev, 0);
gmac_cleanup_rxq(netdev);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
index 79d4a77f72bd..8cabce0eb2ab 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
@@ -616,7 +616,7 @@ static int dpaa2_switch_lag_fdb_add(struct dpaa2_switch_lag *lag,
goto out;
}
- a = kzalloc(sizeof(*a), GFP_KERNEL);
+ a = kzalloc_obj(*a);
if (!a) {
err = -ENOMEM;
goto out;
@@ -4131,8 +4131,7 @@ static int dpaa2_switch_probe(struct fsl_mc_device *sw_dev)
goto err_free_fdbs;
}
- ethsw->lags = kcalloc(ethsw->sw_attr.num_ifs, sizeof(*ethsw->lags),
- GFP_KERNEL);
+ ethsw->lags = kzalloc_objs(*ethsw->lags, ethsw->sw_attr.num_ifs);
if (!ethsw->lags) {
err = -ENOMEM;
goto err_free_filter;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c
index 2784127327e6..6e67a6c9578e 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c
@@ -128,6 +128,7 @@ enum hinic_mbox_tx_status {
#define SEQ_ID_START_VAL 0
#define SEQ_ID_MAX_VAL 42
+#define MBOX_LAST_SEG_MAX_LEN (MBOX_MAX_BUF_SZ - SEQ_ID_MAX_VAL * MBOX_SEG_LEN)
#define NO_DMA_ATTRIBUTE_VAL 0
@@ -372,7 +373,8 @@ recv_pf_from_vf_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
static bool check_mbox_seq_id_and_seg_len(struct hinic_recv_mbox *recv_mbox,
u8 seq_id, u8 seg_len)
{
- if (seq_id > SEQ_ID_MAX_VAL || seg_len > MBOX_SEG_LEN)
+ if (seq_id > SEQ_ID_MAX_VAL || seg_len > MBOX_SEG_LEN ||
+ (seq_id == SEQ_ID_MAX_VAL && seg_len > MBOX_LAST_SEG_MAX_LEN))
return false;
if (seq_id == 0) {
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index ef1ce106f81b..04633103e3e6 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -1051,14 +1051,13 @@ int ice_init_hw(struct ice_hw *hw)
hw->evb_veb = true;
- /* init xarray for identifying scheduling nodes uniquely */
- xa_init_flags(&hw->port_info->sched_node_ids, XA_FLAGS_ALLOC);
+ xa_init_flags(&hw->sched_node_ids, XA_FLAGS_ALLOC);
/* Query the allocated resources for Tx scheduler */
status = ice_sched_query_res_alloc(hw);
if (status) {
ice_debug(hw, ICE_DBG_SCHED, "Failed to get scheduler allocated resources\n");
- goto err_unroll_alloc;
+ goto err_unroll_xarray;
}
ice_sched_get_psm_clk_freq(hw);
@@ -1146,6 +1145,8 @@ err_unroll_fltr_mgmt_struct:
ice_cleanup_fltr_mgmt_struct(hw);
err_unroll_sched:
ice_sched_cleanup_all(hw);
+err_unroll_xarray:
+ xa_destroy(&hw->sched_node_ids);
err_unroll_alloc:
devm_kfree(ice_hw_to_dev(hw), hw->port_info);
err_unroll_cqinit:
@@ -1186,6 +1187,8 @@ void ice_deinit_hw(struct ice_hw *hw)
/* Clear VSI contexts if not already cleared */
ice_clear_all_vsi_ctx(hw);
+
+ xa_destroy(&hw->sched_node_ids);
}
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c
index fff0c1afdb41..ffa18d86729a 100644
--- a/drivers/net/ethernet/intel/ice/ice_sched.c
+++ b/drivers/net/ethernet/intel/ice/ice_sched.c
@@ -371,7 +371,7 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
devm_kfree(ice_hw_to_dev(hw), node->children);
kfree(node->name);
- xa_erase(&pi->sched_node_ids, node->id);
+ xa_erase(&hw->sched_node_ids, node->id);
devm_kfree(ice_hw_to_dev(hw), node);
}
@@ -977,7 +977,7 @@ ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
if (!new_node->name)
return -ENOMEM;
- status = xa_alloc(&pi->sched_node_ids, &new_node->id, NULL, XA_LIMIT(0, UINT_MAX),
+ status = xa_alloc(&hw->sched_node_ids, &new_node->id, NULL, XA_LIMIT(0, UINT_MAX),
GFP_KERNEL);
if (status) {
ice_debug(hw, ICE_DBG_SCHED, "xa_alloc failed for sched node status =%d\n",
diff --git a/drivers/net/ethernet/intel/ice/ice_trace.h b/drivers/net/ethernet/intel/ice/ice_trace.h
index 4f35ef8d6b29..7568c917cdbe 100644
--- a/drivers/net/ethernet/intel/ice/ice_trace.h
+++ b/drivers/net/ethernet/intel/ice/ice_trace.h
@@ -63,23 +63,33 @@
DECLARE_EVENT_CLASS(ice_rx_dim_template,
TP_PROTO(struct ice_q_vector *q_vector, struct dim *dim),
TP_ARGS(q_vector, dim),
- TP_STRUCT__entry(__field(struct ice_q_vector *, q_vector)
- __field(struct dim *, dim)
+ TP_STRUCT__entry(__field(u16, q_index)
+ __field(u8, state)
+ __field(u8, profile_ix)
+ __field(u8, tune_state)
+ __field(u8, steps_right)
+ __field(u8, steps_left)
+ __field(u8, tired)
__string(devname, q_vector->rx.rx_ring->netdev->name)),
- TP_fast_assign(__entry->q_vector = q_vector;
- __entry->dim = dim;
+ TP_fast_assign(__entry->q_index = q_vector->rx.rx_ring->q_index;
+ __entry->state = dim->state;
+ __entry->profile_ix = dim->profile_ix;
+ __entry->tune_state = dim->tune_state;
+ __entry->steps_right = dim->steps_right;
+ __entry->steps_left = dim->steps_left;
+ __entry->tired = dim->tired;
__assign_str(devname);),
TP_printk("netdev: %s Rx-Q: %d dim-state: %d dim-profile: %d dim-tune: %d dim-st-right: %d dim-st-left: %d dim-tired: %d",
__get_str(devname),
- __entry->q_vector->rx.rx_ring->q_index,
- __entry->dim->state,
- __entry->dim->profile_ix,
- __entry->dim->tune_state,
- __entry->dim->steps_right,
- __entry->dim->steps_left,
- __entry->dim->tired)
+ __entry->q_index,
+ __entry->state,
+ __entry->profile_ix,
+ __entry->tune_state,
+ __entry->steps_right,
+ __entry->steps_left,
+ __entry->tired)
);
DEFINE_EVENT(ice_rx_dim_template, ice_rx_dim_work,
@@ -90,23 +100,33 @@ DEFINE_EVENT(ice_rx_dim_template, ice_rx_dim_work,
DECLARE_EVENT_CLASS(ice_tx_dim_template,
TP_PROTO(struct ice_q_vector *q_vector, struct dim *dim),
TP_ARGS(q_vector, dim),
- TP_STRUCT__entry(__field(struct ice_q_vector *, q_vector)
- __field(struct dim *, dim)
+ TP_STRUCT__entry(__field(u16, q_index)
+ __field(u8, state)
+ __field(u8, profile_ix)
+ __field(u8, tune_state)
+ __field(u8, steps_right)
+ __field(u8, steps_left)
+ __field(u8, tired)
__string(devname, q_vector->tx.tx_ring->netdev->name)),
- TP_fast_assign(__entry->q_vector = q_vector;
- __entry->dim = dim;
+ TP_fast_assign(__entry->q_index = q_vector->tx.tx_ring->q_index;
+ __entry->state = dim->state;
+ __entry->profile_ix = dim->profile_ix;
+ __entry->tune_state = dim->tune_state;
+ __entry->steps_right = dim->steps_right;
+ __entry->steps_left = dim->steps_left;
+ __entry->tired = dim->tired;
__assign_str(devname);),
TP_printk("netdev: %s Tx-Q: %d dim-state: %d dim-profile: %d dim-tune: %d dim-st-right: %d dim-st-left: %d dim-tired: %d",
__get_str(devname),
- __entry->q_vector->tx.tx_ring->q_index,
- __entry->dim->state,
- __entry->dim->profile_ix,
- __entry->dim->tune_state,
- __entry->dim->steps_right,
- __entry->dim->steps_left,
- __entry->dim->tired)
+ __entry->q_index,
+ __entry->state,
+ __entry->profile_ix,
+ __entry->tune_state,
+ __entry->steps_right,
+ __entry->steps_left,
+ __entry->tired)
);
DEFINE_EVENT(ice_tx_dim_template, ice_tx_dim_work,
diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
index d9a5c1aae7c2..cf147a212707 100644
--- a/drivers/net/ethernet/intel/ice/ice_type.h
+++ b/drivers/net/ethernet/intel/ice/ice_type.h
@@ -765,7 +765,6 @@ struct ice_port_info {
/* List contain profile ID(s) and other params per layer */
struct list_head rl_prof_list[ICE_AQC_TOPO_MAX_LEVEL_NUM];
struct ice_qos_cfg qos_cfg;
- struct xarray sched_node_ids;
u8 is_vf:1;
u8 is_custom_tx_enabled:1;
};
@@ -930,6 +929,7 @@ struct ice_hw {
u8 sw_entry_point_layer;
u16 max_children[ICE_AQC_TOPO_MAX_LEVEL_NUM];
struct list_head agg_list; /* lists all aggregator */
+ struct xarray sched_node_ids;
struct ice_vsi_ctx *vsi_ctx[ICE_MAX_VSI];
u8 evb_veb; /* true for VEB, false for VEPA */
diff --git a/drivers/net/ethernet/intel/idpf/idpf_main.c b/drivers/net/ethernet/intel/idpf/idpf_main.c
index 9840580fbe51..129bccaa6baa 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_main.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_main.c
@@ -106,6 +106,11 @@ static int idpf_dev_init(struct idpf_adapter *adapter,
*/
static void idpf_decfg_device(struct idpf_adapter *adapter)
{
+ struct pci_dev *pdev = adapter->pdev;
+
+ if (pcie_ptm_enabled(pdev))
+ pci_disable_ptm(pdev);
+
libie_pci_unmap_all_mmio_regions(&adapter->ctlq_ctx.mmio_info);
}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
index 24b91be25676..4311ffa30bb1 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
@@ -3299,6 +3299,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
struct libeth_rx_pt decoded)
{
u16 rsc_segments, rsc_seg_len;
+ u16 l3_start = 0;
bool ipv4, ipv6;
int len;
@@ -3321,7 +3322,10 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
NAPI_GRO_CB(skb)->count = rsc_segments;
skb_shinfo(skb)->gso_size = rsc_seg_len;
- skb_reset_network_header(skb);
+ if (unlikely(eth_type_vlan(skb->protocol)))
+ l3_start = VLAN_HLEN;
+
+ skb_set_network_header(skb, l3_start);
if (ipv4) {
struct iphdr *ipv4h = ip_hdr(skb);
@@ -3329,7 +3333,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
/* Reset and set transport header offset in skb */
- skb_set_transport_header(skb, sizeof(struct iphdr));
+ skb_set_transport_header(skb, l3_start + sizeof(struct iphdr));
len = skb->len - skb_transport_offset(skb);
/* Compute the TCP pseudo header checksum*/
@@ -3339,7 +3343,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
- skb_set_transport_header(skb, sizeof(struct ipv6hdr));
+ skb_set_transport_header(skb, l3_start + sizeof(struct ipv6hdr));
len = skb->len - skb_transport_offset(skb);
tcp_hdr(skb)->check =
~tcp_v6_check(len, &ipv6h->saddr, &ipv6h->daddr, 0);
@@ -4146,6 +4150,26 @@ static void idpf_vport_intr_ena_irq_all(struct idpf_vport *vport,
}
/**
+ * idpf_vport_intr_dis_dim_all - Disable DIM work for all q_vectors
+ * @rsrc: pointer to queue and vector resources
+ *
+ * The DIM works are embedded in the q_vector array that
+ * idpf_vport_intr_rel() frees, and the poll arms them after
+ * napi_complete_done() has already cleared NAPI_STATE_SCHED. Disable
+ * rather than just cancel, so that a poll tail still running past
+ * napi_disable() cannot queue them again behind the drain.
+ */
+static void idpf_vport_intr_dis_dim_all(struct idpf_q_vec_rsrc *rsrc)
+{
+ for (u16 v_idx = 0; v_idx < rsrc->num_q_vectors; v_idx++) {
+ struct idpf_q_vector *q_vector = &rsrc->q_vectors[v_idx];
+
+ disable_work_sync(&q_vector->tx_dim.work);
+ disable_work_sync(&q_vector->rx_dim.work);
+ }
+}
+
+/**
* idpf_vport_intr_deinit - Release all vector associations for the vport
* @vport: main vport structure
* @rsrc: pointer to queue and vector resources
@@ -4155,6 +4179,7 @@ void idpf_vport_intr_deinit(struct idpf_vport *vport,
{
idpf_vport_intr_dis_irq_all(rsrc);
idpf_vport_intr_napi_dis_all(rsrc);
+ idpf_vport_intr_dis_dim_all(rsrc);
idpf_vport_intr_napi_del_all(rsrc);
idpf_vport_intr_rel_irq(vport, rsrc);
}
@@ -4235,7 +4260,6 @@ static void idpf_vport_intr_napi_ena_all(struct idpf_q_vec_rsrc *rsrc)
for (u16 q_idx = 0; q_idx < rsrc->num_q_vectors; q_idx++) {
struct idpf_q_vector *q_vector = &rsrc->q_vectors[q_idx];
- idpf_init_dim(q_vector);
napi_enable(&q_vector->napi);
}
}
@@ -4578,6 +4602,8 @@ int idpf_vport_intr_alloc(struct idpf_vport *vport,
q_coal = &user_config->q_coalesce[v_idx];
q_vector->vport = vport;
+ idpf_init_dim(q_vector);
+
q_vector->tx_itr_value = q_coal->tx_coalesce_usecs;
q_vector->tx_intr_mode = q_coal->tx_intr_mode;
q_vector->tx_itr_idx = VIRTCHNL2_ITR_IDX_1;
diff --git a/drivers/net/ethernet/intel/libie/controlq.c b/drivers/net/ethernet/intel/libie/controlq.c
index 45a49eba6a82..6214fc036ce5 100644
--- a/drivers/net/ethernet/intel/libie/controlq.c
+++ b/drivers/net/ethernet/intel/libie/controlq.c
@@ -157,8 +157,7 @@ static void libie_ctlq_free_tx_msgs(struct libie_ctlq_info *ctlq,
*/
static int libie_ctlq_alloc_tx_msgs(struct libie_ctlq_info *ctlq)
{
- ctlq->tx_msg = kvzalloc_objs(*ctlq->tx_msg, ctlq->ring_len,
- GFP_KERNEL);
+ ctlq->tx_msg = kvzalloc_objs(*ctlq->tx_msg, ctlq->ring_len);
if (!ctlq->tx_msg)
return -ENOMEM;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
index 3070700b952b..2b67671a2bd8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
@@ -3647,7 +3647,7 @@ static int npc_defrag_add_2_show_list(struct rvu *rvu, u16 old_midx,
{
struct npc_defrag_show_node *node;
- node = kcalloc(1, sizeof(*node), GFP_KERNEL);
+ node = kzalloc_objs(*node, 1);
if (!node)
return -ENOMEM;
@@ -4082,7 +4082,7 @@ int npc_cn20k_defrag(struct rvu *rvu)
INIT_LIST_HEAD(&x4lh);
INIT_LIST_HEAD(&x2lh);
- node = kcalloc(npc_priv->num_subbanks, sizeof(*node), GFP_KERNEL);
+ node = kzalloc_objs(*node, npc_priv->num_subbanks);
if (!node)
return -ENOMEM;
@@ -4711,7 +4711,7 @@ static int npc_priv_init(struct rvu *rvu)
return -EINVAL;
}
- npc_priv = kcalloc(1, sizeof(*npc_priv), GFP_KERNEL);
+ npc_priv = kzalloc_objs(*npc_priv, 1);
if (!npc_priv)
return -ENOMEM;
@@ -4729,8 +4729,7 @@ static int npc_priv_init(struct rvu *rvu)
num_banks, bank_depth, num_subbanks, subbank_depth,
npc_kw_name[npc_priv->kw]);
- npc_priv->sb = kcalloc(num_subbanks, sizeof(struct npc_subbank),
- GFP_KERNEL);
+ npc_priv->sb = kzalloc_objs(struct npc_subbank, num_subbanks);
if (!npc_priv->sb)
goto fail1;
@@ -4757,9 +4756,7 @@ static int npc_priv_init(struct rvu *rvu)
/* Get number of pcifuncs in the system */
npc_priv->pf_cnt = npc_pcifunc_map_create(rvu);
- npc_priv->xa_pf2idx_map = kcalloc(npc_priv->pf_cnt,
- sizeof(struct xarray),
- GFP_KERNEL);
+ npc_priv->xa_pf2idx_map = kzalloc_objs(struct xarray, npc_priv->pf_cnt);
if (!npc_priv->xa_pf2idx_map) {
ret = -ENOMEM;
goto fail3;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mcs.c b/drivers/net/ethernet/marvell/octeontx2/af/mcs.c
index a07e0b3d8d00..211c10aa5880 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mcs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mcs.c
@@ -1417,6 +1417,16 @@ static int mcs_x2p_calibration(struct mcs *mcs)
int i, err = 0;
u64 val;
+ /* Clear any stale calibration state left by firmware/bootloader.
+ * Some firmware versions may leave MCSX_MIL_GLOBAL bit 5 set,
+ * preventing the hardware from detecting the rising edge needed to
+ * trigger X2P calibration.
+ */
+ val = mcs_reg_read(mcs, MCSX_MIL_GLOBAL);
+ val &= ~BIT_ULL(5);
+ mcs_reg_write(mcs, MCSX_MIL_GLOBAL, val);
+ usleep_range(100, 200);
+
/* set X2P calibration */
val = mcs_reg_read(mcs, MCSX_MIL_GLOBAL);
val |= BIT_ULL(5);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
index 74c041ab5280..937b085582b5 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -3468,6 +3468,8 @@ err:
return ret;
}
+#define PCI_DEVID_OCTEONTX2_RVU_AFVF 0xA0F8
+
static int rvu_enable_sriov(struct rvu *rvu)
{
struct pci_dev *pdev = rvu->pdev;
@@ -3486,24 +3488,27 @@ static int rvu_enable_sriov(struct rvu *rvu)
return 0;
pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID, &rvu->vf_devid);
- chans = rvu_get_num_lbk_chans();
- if (chans < 0)
- return chans;
-
vfs = pci_sriov_get_totalvfs(pdev);
-
- /* Limit VFs in case we have more VFs than LBK channels available. */
- if (vfs > chans)
- vfs = chans;
-
if (!vfs)
return 0;
- /* LBK channel number 63 is used for switching packets between
- * CGX mapped VFs. Hence limit LBK pairs till 62 only.
- */
- if (vfs > 62)
- vfs = 62;
+ if (rvu->vf_devid == PCI_DEVID_OCTEONTX2_RVU_AFVF) {
+ chans = rvu_get_num_lbk_chans();
+ if (chans < 0)
+ return chans;
+
+ /* The last LBK channel is reserved for switching packets between
+ * CGX mapped VFs. Also, since LBK VFs work in pairs, limit VF
+ * count to available LBK channels minus 2.
+ */
+ vfs = min(vfs, chans - 2);
+
+ if (vfs <= 0) {
+ dev_warn(&pdev->dev,
+ "Skipping SRIOV enablement, not enough LBK channels available\n");
+ return 0;
+ }
+ }
/* Save VFs number for reference in VF interrupts handlers.
* Since interrupts might start arriving during SRIOV enablement
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
index 22ee99676879..904374baae6f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
@@ -829,19 +829,25 @@ static int rvu_dbg_rvu_pf_cgx_map_display(struct seq_file *filp, void *unused)
int pf, domain, blkid;
u8 cgx_id, lmac_id;
u16 pcifunc;
+ u8 start;
- domain = 2;
+ domain = pci_domain_nr(rvu->pdev->bus);
mac_ops = get_mac_ops(rvu_first_cgx_pdata(rvu));
/* There can be no CGX devices at all */
if (!mac_ops)
return 0;
seq_printf(filp, "PCI dev\t\tRVU PF Func\tNIX block\t%s\tLMAC\tCHAN\n",
mac_ops->name);
+
+ /* All the PF devices are on contiguous PCI bus numbers, but the PF0(AF)
+ * may not start from 1 always. Hence get domain and bus from PCI device.
+ */
+ start = rvu->pdev->bus->number;
for (pf = 0; pf < rvu->hw->total_pfs; pf++) {
if (!is_pf_cgxmapped(rvu, pf))
continue;
- pdev = pci_get_domain_bus_and_slot(domain, pf + 1, 0);
+ pdev = pci_get_domain_bus_and_slot(domain, pf + start, 0);
if (!pdev)
continue;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
index 60922944675b..c34f8d86cc8a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
@@ -2957,10 +2957,9 @@ static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam,
}
}
- /* Disable the entry */
- npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);
-
if (!cn20k_dft_rl) {
+ /* Disable the entry */
+ npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);
mcam->entry2pfvf_map[index] = NPC_MCAM_INVALID_MAP;
/* Free the entry in bitmap */
npc_mcam_clear_bit(mcam, index);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
index 69c0911e28e9..f160b1618efa 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
@@ -235,13 +235,63 @@ static int otx2_qos_txschq_set_parent_topology(struct otx2_nic *pfvf,
return rc;
}
+static int otx2_qos_reset_schq_topology(struct otx2_nic *pfvf, u16 lvl,
+ u16 schq)
+{
+ struct mbox *mbox = &pfvf->mbox;
+ struct nix_txschq_config *cfg;
+ int rc;
+
+ if (lvl < NIX_TXSCH_LVL_TL4 || lvl >= NIX_TXSCH_LVL_TL1)
+ return 0;
+
+ mutex_lock(&mbox->lock);
+
+ cfg = otx2_mbox_alloc_msg_nix_txschq_cfg(mbox);
+ if (!cfg) {
+ mutex_unlock(&mbox->lock);
+ return -ENOMEM;
+ }
+
+ cfg->lvl = lvl;
+ cfg->num_regs = 1;
+
+ if (lvl == NIX_TXSCH_LVL_TL4)
+ cfg->reg[0] = NIX_AF_TL4X_TOPOLOGY(schq);
+ else if (lvl == NIX_TXSCH_LVL_TL3)
+ cfg->reg[0] = NIX_AF_TL3X_TOPOLOGY(schq);
+ else if (lvl == NIX_TXSCH_LVL_TL2)
+ cfg->reg[0] = NIX_AF_TL2X_TOPOLOGY(schq);
+
+ cfg->regval[0] = 0;
+
+ rc = otx2_sync_mbox_msg(mbox);
+
+ mutex_unlock(&mbox->lock);
+
+ return rc;
+}
+
+static void otx2_qos_free_hw_schq(struct otx2_nic *pfvf, u16 lvl, u16 schq)
+{
+ int err;
+
+ err = otx2_qos_reset_schq_topology(pfvf, lvl, schq);
+ if (err)
+ netdev_warn(pfvf->netdev,
+ "QoS: failed to reset topology for schq %u at level %u: %d\n",
+ schq, lvl, err);
+
+ otx2_txschq_free_one(pfvf, lvl, schq);
+}
+
static void otx2_qos_free_hw_node_schq(struct otx2_nic *pfvf,
struct otx2_qos_node *parent)
{
struct otx2_qos_node *node;
list_for_each_entry_reverse(node, &parent->child_schq_list, list)
- otx2_txschq_free_one(pfvf, node->level, node->schq);
+ otx2_qos_free_hw_schq(pfvf, node->level, node->schq);
}
static void otx2_qos_free_hw_node(struct otx2_nic *pfvf,
@@ -252,7 +302,7 @@ static void otx2_qos_free_hw_node(struct otx2_nic *pfvf,
list_for_each_entry_safe(node, tmp, &parent->child_list, list) {
otx2_qos_free_hw_node(pfvf, node);
otx2_qos_free_hw_node_schq(pfvf, node);
- otx2_txschq_free_one(pfvf, node->level, node->schq);
+ otx2_qos_free_hw_schq(pfvf, node->level, node->schq);
}
}
@@ -266,7 +316,7 @@ static void otx2_qos_free_hw_cfg(struct otx2_nic *pfvf,
otx2_qos_free_hw_node_schq(pfvf, node);
/* free node hw mappings */
- otx2_txschq_free_one(pfvf, node->level, node->schq);
+ otx2_qos_free_hw_schq(pfvf, node->level, node->schq);
mutex_unlock(&pfvf->qos.qos_lock);
}
@@ -913,7 +963,7 @@ static void otx2_qos_free_cfg(struct otx2_nic *pfvf, struct otx2_qos_cfg *cfg)
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
for (idx = 0; idx < cfg->schq[lvl]; idx++) {
schq = cfg->schq_list[lvl][idx];
- otx2_txschq_free_one(pfvf, lvl, schq);
+ otx2_qos_free_hw_schq(pfvf, lvl, schq);
}
}
@@ -921,7 +971,7 @@ static void otx2_qos_free_cfg(struct otx2_nic *pfvf, struct otx2_qos_cfg *cfg)
for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) {
if (cfg->schq_index_used[lvl][idx]) {
schq = cfg->schq_contig_list[lvl][idx];
- otx2_txschq_free_one(pfvf, lvl, schq);
+ otx2_qos_free_hw_schq(pfvf, lvl, schq);
}
}
}
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index be3bd025c41a..fd7a49ae88d0 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4828,7 +4828,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
phy_interface_t phy_mode;
struct phylink *phylink;
struct mtk_mac *mac;
- int id, err;
+ int id, err, i;
int txqs = 1;
u32 val;
@@ -4907,8 +4907,8 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
mac->phylink_config.type = PHYLINK_NETDEV;
mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
- mac->phylink_config.lpi_capabilities = MAC_100FD | MAC_1000FD |
- MAC_2500FD;
+ /* LPI above 1 Gbps is not supported */
+ mac->phylink_config.lpi_capabilities = MAC_100FD | MAC_1000FD;
mac->phylink_config.lpi_timer_default = 1000;
/* MT7623 gmac0 is now missing its speed-specific PLL configuration
@@ -4966,6 +4966,18 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
mac->phylink_config.supported_interfaces);
+ /* LPI wake-up timing is only verified on MTK_GMAC_EEE SoCs */
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC_EEE)) {
+ phy_interface_copy(mac->phylink_config.lpi_interfaces,
+ mac->phylink_config.supported_interfaces);
+ __clear_bit(PHY_INTERFACE_MODE_2500BASEX,
+ mac->phylink_config.lpi_interfaces);
+ for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
+ if (mtk_interface_mode_is_xgmii(eth, i))
+ __clear_bit(i,
+ mac->phylink_config.lpi_interfaces);
+ }
+
phylink = phylink_create(&mac->phylink_config,
of_fwnode_handle(mac->of_node),
phy_mode, mac_ops);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 0168e2fbc619..88a9b3b23bea 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -994,6 +994,7 @@ enum mkt_eth_capabilities {
MTK_U3_COPHY_V2_BIT,
MTK_SRAM_BIT,
MTK_36BIT_DMA_BIT,
+ MTK_GMAC_EEE_BIT,
/* MUX BITS*/
MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT,
@@ -1034,6 +1035,7 @@ enum mkt_eth_capabilities {
#define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT)
#define MTK_SRAM BIT_ULL(MTK_SRAM_BIT)
#define MTK_36BIT_DMA BIT_ULL(MTK_36BIT_DMA_BIT)
+#define MTK_GMAC_EEE BIT_ULL(MTK_GMAC_EEE_BIT)
#define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \
BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT)
@@ -1117,7 +1119,7 @@ enum mkt_eth_capabilities {
#define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
- MTK_RSTCTRL_PPE1 | MTK_SRAM)
+ MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_GMAC_EEE)
#define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
index 6049ccf475bc..a4c096a4fed2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
@@ -557,6 +557,7 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u16 fec_policy)
u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
int sz = MLX5_ST_SZ_BYTES(pplm_reg);
u16 fec_policy_auto = 0;
+ bool fec_set = false;
int err;
int i;
@@ -569,9 +570,6 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u16 fec_policy)
if (fec_policy >= (1 << MLX5E_FEC_LLRS_272_257_1) && !fec_50g_per_lane)
return -EOPNOTSUPP;
- if (fec_policy && !mlx5e_fec_in_caps(dev, fec_policy))
- return -EOPNOTSUPP;
-
MLX5_SET(pplm_reg, in, local_port, 1);
err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
if (err)
@@ -591,12 +589,17 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u16 fec_policy)
mlx5e_get_fec_cap_field(out, &fec_caps, i);
/* policy supported for link speed */
- if (fec_caps & conf_fec)
+ if (fec_caps & conf_fec) {
mlx5e_fec_admin_field(out, &conf_fec, 1, i);
- else
- /* set FEC to auto*/
+ fec_set = true;
+ } else {
+ /* set FEC to auto */
mlx5e_fec_admin_field(out, &fec_policy_auto, 1, i);
+ }
}
+ if (fec_policy && !fec_set)
+ return -EOPNOTSUPP;
+
return mlx5_core_access_reg(dev, out, sz, out, sz, MLX5_REG_PPLM, 0, 1);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
index fa2283dd383b..53dbdf77bcce 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
@@ -66,4 +66,8 @@ enum {
MLX5E_FEC_LLRS_272_257_1 = 9,
};
+#define MLX5E_FEC_RS_MASK (BIT(MLX5E_FEC_RS_528_514) | \
+ BIT(MLX5E_FEC_RS_544_514_INTERLEAVED_QUAD) | \
+ BIT(MLX5E_FEC_RS_544_514))
+
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c
index 89490f687a9c..93c62d3f3e5b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c
@@ -311,12 +311,15 @@ err_alloc:
static void
sample_restore_put(struct mlx5e_tc_psample *tc_psample, struct mlx5e_sample_restore *restore)
{
+ bool last;
+
mutex_lock(&tc_psample->restore_lock);
- if (--restore->count == 0)
+ last = --restore->count == 0;
+ if (last)
hash_del(&restore->hlist);
mutex_unlock(&tc_psample->restore_lock);
- if (!restore->count) {
+ if (last) {
mlx5_del_flow_rules(restore->rule);
mlx5_modify_header_dealloc(tc_psample->esw->dev, restore->modify_hdr);
kfree(restore);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
index 4f984f6a2cb9..55ec6387ab28 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
@@ -3,6 +3,7 @@
#include "rx.h"
#include "en/xdp.h"
+#include <linux/bitmap.h>
#include <net/xdp_sock_drv.h>
#include <linux/filter.h>
@@ -156,6 +157,7 @@ err_reuse_batch:
xsk_buff_free(xsk_buffs[batch]);
err:
+ bitmap_fill(wi->skip_release_bitmap, rq->mpwqe.pages_per_wqe);
rq->stats->buff_alloc_err++;
return -ENOMEM;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index 00e706e1ede1..741f75b5bfec 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -148,7 +148,7 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
if (err)
return err;
- if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC &&
+ if (priv->dcbx.tc_tsa[i] == IEEE_8021QAZ_TSA_ETS &&
tc_group[i] == (MLX5E_LOWEST_PRIO_GROUP + 1))
is_zero_bw_ets_tc = true;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 112926d07634..3ed59ced0407 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -1002,9 +1002,9 @@ static u32 pplm2ethtool_fec(u_long fec_mode, unsigned long size)
return 0;
}
-#define MLX5E_ADVERTISE_SUPPORTED_FEC(mlx5_fec, ethtool_fec) \
+#define MLX5E_ADVERTISE_SUPPORTED_FEC(fec_mask, ethtool_fec) \
do { \
- if (mlx5e_fec_in_caps(dev, 1 << (mlx5_fec))) \
+ if (mlx5e_fec_in_caps(dev, fec_mask)) \
__set_bit(ethtool_fec, \
link_ksettings->link_modes.supported);\
} while (0)
@@ -1013,6 +1013,7 @@ static const u32 pplm_fec_2_ethtool_linkmodes[] = {
[MLX5E_FEC_NOFEC] = ETHTOOL_LINK_MODE_FEC_NONE_BIT,
[MLX5E_FEC_FIRECODE] = ETHTOOL_LINK_MODE_FEC_BASER_BIT,
[MLX5E_FEC_RS_528_514] = ETHTOOL_LINK_MODE_FEC_RS_BIT,
+ [MLX5E_FEC_RS_544_514_INTERLEAVED_QUAD] = ETHTOOL_LINK_MODE_FEC_RS_BIT,
[MLX5E_FEC_RS_544_514] = ETHTOOL_LINK_MODE_FEC_RS_BIT,
[MLX5E_FEC_LLRS_272_257_1] = ETHTOOL_LINK_MODE_FEC_LLRS_BIT,
};
@@ -1029,13 +1030,13 @@ static int get_fec_supported_advertised(struct mlx5_core_dev *dev,
if (err)
return (err == -EOPNOTSUPP) ? 0 : err;
- MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_NOFEC,
+ MLX5E_ADVERTISE_SUPPORTED_FEC(BIT(MLX5E_FEC_NOFEC),
ETHTOOL_LINK_MODE_FEC_NONE_BIT);
- MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_FIRECODE,
+ MLX5E_ADVERTISE_SUPPORTED_FEC(BIT(MLX5E_FEC_FIRECODE),
ETHTOOL_LINK_MODE_FEC_BASER_BIT);
- MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_RS_528_514,
+ MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_RS_MASK,
ETHTOOL_LINK_MODE_FEC_RS_BIT);
- MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_LLRS_272_257_1,
+ MLX5E_ADVERTISE_SUPPORTED_FEC(BIT(MLX5E_FEC_LLRS_272_257_1),
ETHTOOL_LINK_MODE_FEC_LLRS_BIT);
active_fec_long = active_fec;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index ce765692fd19..88a170e40bd9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -56,7 +56,6 @@
#include "lib/vxlan.h"
#define CREATE_TRACE_POINTS
#include "diag/en_rep_tracepoint.h"
-#include "diag/reporter_vnic.h"
#include "en_accel/ipsec.h"
#include "en/tc/int_port.h"
#include "en/ptp.h"
@@ -1439,51 +1438,6 @@ static unsigned int mlx5e_ul_rep_stats_grps_num(struct mlx5e_priv *priv)
return ARRAY_SIZE(mlx5e_ul_rep_stats_grps);
}
-static int
-mlx5e_rep_vnic_reporter_diagnose(struct devlink_health_reporter *reporter,
- struct devlink_fmsg *fmsg,
- struct netlink_ext_ack *extack)
-{
- struct mlx5e_rep_priv *rpriv = devlink_health_reporter_priv(reporter);
- struct mlx5_eswitch_rep *rep = rpriv->rep;
-
- mlx5_reporter_vnic_diagnose_counters(rep->esw->dev, fmsg, rep->vport,
- true);
- return 0;
-}
-
-static const struct devlink_health_reporter_ops mlx5_rep_vnic_reporter_ops = {
- .name = "vnic",
- .diagnose = mlx5e_rep_vnic_reporter_diagnose,
-};
-
-static void mlx5e_rep_vnic_reporter_create(struct mlx5e_priv *priv,
- struct devlink_port *dl_port)
-{
- struct mlx5e_rep_priv *rpriv = priv->ppriv;
- struct devlink_health_reporter *reporter;
-
- reporter = devl_port_health_reporter_create(dl_port,
- &mlx5_rep_vnic_reporter_ops,
- rpriv);
- if (IS_ERR(reporter)) {
- mlx5_core_err(priv->mdev,
- "Failed to create representor vnic reporter, err = %pe\n",
- reporter);
- return;
- }
-
- rpriv->rep_vnic_reporter = reporter;
-}
-
-static void mlx5e_rep_vnic_reporter_destroy(struct mlx5e_priv *priv)
-{
- struct mlx5e_rep_priv *rpriv = priv->ppriv;
-
- if (!IS_ERR_OR_NULL(rpriv->rep_vnic_reporter))
- devl_health_reporter_destroy(rpriv->rep_vnic_reporter);
-}
-
static const struct mlx5e_profile mlx5e_rep_profile = {
.init = mlx5e_init_rep,
.cleanup = mlx5e_cleanup_rep,
@@ -1607,10 +1561,8 @@ mlx5e_vport_vf_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch,
rpriv->rep->vport);
- if (!IS_ERR(dl_port)) {
+ if (!IS_ERR(dl_port))
SET_NETDEV_DEVLINK_PORT(netdev, dl_port);
- mlx5e_rep_vnic_reporter_create(priv, dl_port);
- }
err = register_netdev(netdev);
if (err) {
@@ -1623,7 +1575,6 @@ mlx5e_vport_vf_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
return 0;
err_detach_netdev:
- mlx5e_rep_vnic_reporter_destroy(priv);
mlx5e_detach_netdev(netdev_priv(netdev));
err_cleanup_profile:
priv->profile->cleanup(priv);
@@ -1681,7 +1632,6 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
}
unregister_netdev(netdev);
- mlx5e_rep_vnic_reporter_destroy(priv);
mlx5e_detach_netdev(priv);
priv->profile->cleanup(priv);
mlx5e_destroy_netdev(netdev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
index 70640fa1ad7b..bcd7b4e814d0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
@@ -118,7 +118,6 @@ struct mlx5e_rep_priv {
struct rtnl_link_stats64 prev_vf_vport_stats;
struct mlx5_flow_handle *send_to_vport_meta_rule;
struct rhashtable tc_ht;
- struct devlink_health_reporter *rep_vnic_reporter;
};
static inline
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 206cf9db3466..7bd0606a5253 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -410,8 +410,11 @@ static inline void mlx5e_free_rx_wqe(struct mlx5e_rq *rq,
static void mlx5e_xsk_free_rx_wqe(struct mlx5e_wqe_frag_info *wi)
{
- if (!(wi->flags & BIT(MLX5E_WQE_FRAG_SKIP_RELEASE)))
- xsk_buff_free(*wi->xskp);
+ if (wi->flags & BIT(MLX5E_WQE_FRAG_SKIP_RELEASE))
+ return;
+
+ xsk_buff_free(*wi->xskp);
+ wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
}
static void mlx5e_dealloc_rx_wqe(struct mlx5e_rq *rq, u16 ix)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
index e7e6db7f6bf1..cd94bb44f6ab 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
@@ -1199,50 +1199,39 @@ void mlx5e_stats_rmon_get(struct mlx5e_priv *priv,
void mlx5e_stats_ts_get(struct mlx5e_priv *priv,
struct ethtool_ts_stats *ts_stats)
{
- int i, j;
+ u16 nch = mlx5e_stats_nch_read(priv);
+ int i, tc;
- mutex_lock(&priv->state_lock);
+ ts_stats->pkts = 0;
- if (priv->tx_ptp_opened) {
- struct mlx5e_ptp *ptp = priv->channels.ptp;
+ for (i = 0; i < nch; i++) {
+ struct mlx5e_channel_stats *channel_stats =
+ priv->channel_stats[i];
- ts_stats->pkts = 0;
+ for (tc = 0; tc < priv->max_opened_tc; tc++)
+ ts_stats->pkts += channel_stats->sq[tc].timestamps;
+ }
+
+ /* Accumulate DMA and port timestamp counters so values stay monotonic
+ * across channel teardown and mode switches.
+ */
+ if (priv->tx_ptp_opened) {
+ /* Err and Lost stats are only relevant for port timestamping,
+ * as the DMA layer will always successfully timestamp packets.
+ */
ts_stats->err = 0;
ts_stats->lost = 0;
- if (!ptp)
- goto out;
-
- /* Aggregate stats across all TCs */
- for (i = 0; i < ptp->num_tc; i++) {
+ for (tc = 0; tc < priv->max_opened_tc; tc++) {
struct mlx5e_ptp_cq_stats *stats =
- ptp->ptpsq[i].cq_stats;
+ &priv->ptp_stats.cq[tc];
ts_stats->pkts += stats->cqe;
ts_stats->err += stats->abort + stats->err_cqe +
- stats->late_cqe;
+ stats->late_cqe;
ts_stats->lost += stats->lost_cqe;
}
- } else {
- /* DMA layer will always successfully timestamp packets. Other
- * counters do not make sense for this layer.
- */
- ts_stats->pkts = 0;
-
- /* Aggregate stats across all SQs */
- for (j = 0; j < priv->channels.num; j++) {
- struct mlx5e_channel *c = priv->channels.c[j];
-
- for (i = 0; i < c->num_tc; i++) {
- struct mlx5e_sq_stats *stats = c->sq[i].stats;
-
- ts_stats->pkts += stats->timestamps;
- }
- }
}
-
-out:
- mutex_unlock(&priv->state_lock);
}
#define PPORT_PHY_LAYER_OFF(c) \
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
index 36b00a856bc2..fdc960ea5331 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
@@ -4,6 +4,26 @@
#include <linux/mlx5/driver.h>
#include "eswitch.h"
#include "devlink.h"
+#include "diag/reporter_vnic.h"
+
+static int
+mlx5_esw_rep_vnic_reporter_diagnose(struct devlink_health_reporter *reporter,
+ struct devlink_fmsg *fmsg,
+ struct netlink_ext_ack *extack)
+{
+ struct mlx5_vport *vport = devlink_health_reporter_priv(reporter);
+
+ mlx5_reporter_vnic_diagnose_counters(vport->dev, fmsg, vport->vport,
+ true);
+
+ return 0;
+}
+
+static const
+struct devlink_health_reporter_ops mlx5_esw_rep_vnic_reporter_ops = {
+ .name = "vnic",
+ .diagnose = mlx5_esw_rep_vnic_reporter_diagnose,
+};
static void
mlx5_esw_get_port_parent_id(struct mlx5_core_dev *dev, struct netdev_phys_item_id *ppid)
@@ -220,6 +240,7 @@ static void mlx5_esw_devlink_port_res_unregister(struct devlink_port *dl_port)
int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
{
+ struct devlink_health_reporter *reporter;
struct mlx5_core_dev *dev = esw->dev;
const struct devlink_port_ops *ops;
struct mlx5_devlink_port *dl_port;
@@ -255,6 +276,16 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, struct mlx
mlx5_core_dbg(dev, "Failed to register port resources: %d\n",
err);
+ reporter = devl_port_health_reporter_create(
+ &dl_port->dl_port, &mlx5_esw_rep_vnic_reporter_ops,
+ vport);
+ if (IS_ERR(reporter))
+ mlx5_core_err(dev,
+ "Failed to create vnic health reporter for vport %d: %pe\n",
+ vport_num, reporter);
+ else
+ dl_port->vnic_reporter = reporter;
+
return 0;
rate_err:
@@ -269,6 +300,12 @@ void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_vport *vport)
if (!vport->dl_port)
return;
dl_port = vport->dl_port;
+
+ if (dl_port->vnic_reporter) {
+ devl_health_reporter_destroy(dl_port->vnic_reporter);
+ dl_port->vnic_reporter = NULL;
+ }
+
mlx5_esw_devlink_port_res_unregister(&dl_port->dl_port);
devl_rate_leaf_destroy(&dl_port->dl_port);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index b6e2c153b4f7..fc197d1dc9df 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -1040,13 +1040,19 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
(vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled))
esw->enabled_ipsec_vf_count--;
+ /* Clear rx-mode before esw_vport_change_handle_locked(): on
+ * MLX5_VPORT_PROMISC_CHANGE it calls esw_update_vport_mc_promisc()
+ * when vport->allmulti_rule is set, repopulating mc_list with FDB
+ * rules that dangle once the FDB is destroyed. NULL allmulti_rule
+ * here skips that path.
+ */
+ esw_apply_vport_rx_mode(esw, vport, false, false);
/* We don't assume VFs will cleanup after themselves.
* Calling vport change handler while vport is disabled will cleanup
* the vport resources.
*/
esw_vport_change_handle_locked(vport);
vport->enabled_events = 0;
- esw_apply_vport_rx_mode(esw, vport, false, false);
esw_vport_cleanup(esw, vport);
esw->enabled_vports--;
@@ -2288,8 +2294,7 @@ static int mlx5_esw_spfs_init(struct mlx5_eswitch *esw)
if (!num_entries)
goto out_free;
- esw_funcs->spfs = kcalloc(num_entries, sizeof(*esw_funcs->spfs),
- GFP_KERNEL);
+ esw_funcs->spfs = kzalloc_objs(*esw_funcs->spfs, num_entries);
if (!esw_funcs->spfs) {
err = -ENOMEM;
goto out_free;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index c655f6e8da1c..8b1f93b13ea9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -189,6 +189,7 @@ struct mlx5_vport;
struct mlx5_devlink_port {
struct devlink_port dl_port;
struct mlx5_vport *vport;
+ struct devlink_health_reporter *vnic_reporter;
};
static inline void mlx5_devlink_port_init(struct mlx5_devlink_port *dl_port,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index d603e294ee0e..eb74b6260168 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -1524,7 +1524,7 @@ struct mlx5_flow_handle *
mlx5_esw_lag_demux_rule_create(struct mlx5_eswitch *esw, u16 vport_num,
struct mlx5_flow_table *lag_ft)
{
- struct mlx5_flow_spec *spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+ struct mlx5_flow_spec *spec = kvzalloc_obj(*spec);
struct mlx5_flow_destination dest = {};
struct mlx5_flow_act flow_act = {};
struct mlx5_flow_handle *ret;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c
index 19f65d4c4def..d43f07360159 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c
@@ -163,12 +163,15 @@ void
mlx5_eswitch_termtbl_put(struct mlx5_eswitch *esw,
struct mlx5_termtbl_handle *tt)
{
+ bool last;
+
mutex_lock(&esw->offloads.termtbl_mutex);
- if (--tt->ref_count == 0)
+ last = (--tt->ref_count == 0);
+ if (last)
hash_del(&tt->termtbl_hlist);
mutex_unlock(&esw->offloads.termtbl_mutex);
- if (!tt->ref_count) {
+ if (last) {
mlx5_del_flow_rules(tt->rule);
mlx5_destroy_flow_table(tt->termtbl);
kfree(tt);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index 2285c889c215..c655f6e32e9b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -63,14 +63,15 @@ static int get_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags)
return MLX5_LAG_PORT_SELECT_MODE_QUEUE_AFFINITY;
}
-static u8 lag_active_port_bits(struct mlx5_lag *ldev)
+static u8 lag_active_port_bits(struct mlx5_lag *ldev,
+ struct lag_tracker *tracker)
{
u8 enabled_ports[MLX5_MAX_PORTS] = {};
u8 active_port = 0;
int num_enabled;
int idx;
- mlx5_infer_tx_enabled(&ldev->tracker, ldev, enabled_ports,
+ mlx5_infer_tx_enabled(tracker, ldev, enabled_ports,
&num_enabled);
for (idx = 0; idx < num_enabled; idx++)
active_port |= BIT_MASK(enabled_ports[idx]);
@@ -79,7 +80,8 @@ static u8 lag_active_port_bits(struct mlx5_lag *ldev)
}
static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, struct mlx5_lag *ldev,
- int mode, unsigned long flags)
+ struct lag_tracker *tracker, int mode,
+ unsigned long flags)
{
bool fdb_sel_mode = test_bit(MLX5_LAG_MODE_FLAG_FDB_SEL_MODE_NATIVE,
&flags);
@@ -108,7 +110,7 @@ static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, struct mlx5_lag *ldev,
break;
MLX5_SET(lagc, lag_ctx, active_port,
- lag_active_port_bits(mlx5_lag_dev(dev)));
+ lag_active_port_bits(ldev, tracker));
break;
default:
break;
@@ -787,7 +789,8 @@ static int mlx5_cmd_modify_active_port(struct mlx5_core_dev *dev, u8 ports)
return mlx5_cmd_exec_in(dev, modify_lag, in);
}
-static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 *ports)
+static int _mlx5_modify_lag(struct mlx5_lag *ldev,
+ struct lag_tracker *tracker, u8 *ports)
{
int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
struct mlx5_core_dev *dev0;
@@ -804,7 +807,7 @@ static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 *ports)
!MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table_bypass))
return ret;
- active_ports = lag_active_port_bits(ldev);
+ active_ports = lag_active_port_bits(ldev, tracker);
return mlx5_cmd_modify_active_port(dev0, active_ports);
}
@@ -868,7 +871,7 @@ void mlx5_modify_lag(struct mlx5_lag *ldev,
idx = i * ldev->buckets + j;
if (ports[idx] == ldev->v2p_map[idx])
continue;
- err = _mlx5_modify_lag(ldev, ports);
+ err = _mlx5_modify_lag(ldev, tracker, ports);
if (err) {
mlx5_core_err(dev0,
"Failed to modify LAG (%d)\n",
@@ -976,7 +979,7 @@ static int mlx5_create_lag(struct mlx5_lag *ldev,
mlx5_core_info(dev0, "shared_fdb:%d mode:%s\n",
shared_fdb, mlx5_get_str_port_sel_mode(mode, flags));
- err = mlx5_cmd_create_lag(dev0, ldev, mode, flags);
+ err = mlx5_cmd_create_lag(dev0, ldev, tracker, mode, flags);
if (err) {
mlx5_core_err(dev0,
"Failed to create LAG (%d)\n",
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c
index 95a8b1e64ba4..1724bf7e0e7a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c
@@ -317,7 +317,7 @@ int mlx5_sf_hw_table_init(struct mlx5_core_dev *dev)
num_spfs = mlx5_esw_get_num_spfs(dev);
num_hwc = MLX5_SF_HWC_FIRST_SPF + num_spfs;
- table->hwc = kcalloc(num_hwc, sizeof(*table->hwc), GFP_KERNEL);
+ table->hwc = kzalloc_objs(*table->hwc, num_hwc);
if (!table->hwc) {
err = -ENOMEM;
goto hwc_alloc_err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c
index fa4d24b3dfaa..1b928b40686e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c
@@ -239,7 +239,7 @@ static int dr_icm_buddy_init_ste_cache(struct mlx5dr_icm_buddy_mem *buddy)
if (!buddy->hw_ste_arr)
goto free_ste_arr;
- buddy->miss_list = kvmalloc_array(num_of_entries, sizeof(struct list_head), GFP_KERNEL);
+ buddy->miss_list = kvmalloc_objs(struct list_head, num_of_entries);
if (!buddy->miss_list)
goto free_hw_ste_arr;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
index 9939749c47bc..9c5862f4e16a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
@@ -572,6 +572,38 @@ mlxsw_sp1_ptp_unmatched_remove(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp1_ptp_unmatched_ht_params);
}
+/* mlxsw_sp1_ptp_packet_finish() is reached both from the NAPI poll context
+ * (mlxsw_sp1_ptp_got_packet(), mlxsw_sp1_ptp_got_piece() and
+ * mlxsw_sp1_packet_timestamp()) and from process context, by way of the GC
+ * workqueue (mlxsw_sp1_ptp_ht_gc_collect() ->
+ * mlxsw_sp1_ptp_unmatched_finish()).
+ *
+ * mlxsw_sp_rx_listener_no_mark_func() ends in napi_gro_receive(), using the
+ * NAPI pointer that was placed in the SKB control block when the trapped
+ * packet was received in the NAPI context. That pointer may only be used
+ * from its own poll context, which this call site cannot guarantee.
+ *
+ * netif_receive_skb(), unlike napi_gro_receive(), can be called from outside
+ * of the NAPI instance's poll context. RX stats accounting and the skb->dev
+ * assignment are still preserved; the only change is the delivery call.
+ */
+static void mlxsw_sp1_ptp_rx_finish(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct sk_buff *skb)
+{
+ struct mlxsw_sp_port_pcpu_stats *pcpu_stats;
+
+ skb->dev = mlxsw_sp_port->dev;
+
+ pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats);
+ u64_stats_update_begin(&pcpu_stats->syncp);
+ pcpu_stats->rx_packets++;
+ pcpu_stats->rx_bytes += skb->len;
+ u64_stats_update_end(&pcpu_stats->syncp);
+
+ skb->protocol = eth_type_trans(skb, skb->dev);
+ netif_receive_skb(skb);
+}
+
/* This function is called in the following scenarios:
*
* 1) When a packet is matched with its timestamp.
@@ -600,7 +632,7 @@ static void mlxsw_sp1_ptp_packet_finish(struct mlxsw_sp *mlxsw_sp,
if (ingress) {
if (hwtstamps)
*skb_hwtstamps(skb) = *hwtstamps;
- mlxsw_sp_rx_listener_no_mark_func(skb, local_port, mlxsw_sp);
+ mlxsw_sp1_ptp_rx_finish(mlxsw_sp_port, skb);
} else {
/* skb_tstamp_tx() allows hwtstamps to be NULL. */
skb_tstamp_tx(skb, hwtstamps);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_irq.c b/drivers/net/ethernet/meta/fbnic/fbnic_irq.c
index 5e383d40abc7..ec3b628ecb2d 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_irq.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_irq.c
@@ -282,7 +282,7 @@ enum fbnic_msix_self_test_codes fbnic_msix_test(struct fbnic_dev *fbd)
int i;
/* Allocate bitmap and IRQ vector table */
- test_data = kzalloc_obj(*test_data, GFP_KERNEL);
+ test_data = kzalloc_obj(*test_data);
/* memory allocation failure */
if (!test_data)
diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c
index 4afbb40bc0e4..d49f281c7867 100644
--- a/drivers/net/ethernet/micrel/ks8851_common.c
+++ b/drivers/net/ethernet/micrel/ks8851_common.c
@@ -143,9 +143,6 @@ static int ks8851_write_mac_addr(struct net_device *dev)
ks8851_wrreg16(ks, KS_MAR(i), val);
}
- if (!netif_running(dev))
- ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN);
-
ks8851_unlock(ks);
return 0;
@@ -478,8 +475,7 @@ static int ks8851_net_open(struct net_device *dev)
* @dev: The device being closed.
*
* Called to close down a network device which has been active. Cancel any
- * work, shutdown the RX and TX process and then place the chip into a low
- * power state whilst it is not being used.
+ * work and shutdown the RX and TX process.
*/
static int ks8851_net_stop(struct net_device *dev)
{
@@ -506,8 +502,6 @@ static int ks8851_net_stop(struct net_device *dev)
/* shutdown TX process */
ks8851_wrreg16(ks, KS_TXCR, 0x0000);
- /* set powermode to soft power down to save power */
- ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN);
ks8851_unlock(ks);
/* ensure any queued tx buffers are dumped */
diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
index f92b2d0bf926..8e9bfc1d6a2a 100644
--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
+++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
@@ -429,11 +429,11 @@ int mana_gd_alloc_memory(struct gdma_context *gc, unsigned int length,
/* length is a power of 2 above PAGE_SIZE, so this divides exactly. */
npages = length / PAGE_SIZE;
- gmi->pages_va = kvcalloc(npages, sizeof(*gmi->pages_va), GFP_KERNEL);
+ gmi->pages_va = kvzalloc_objs(*gmi->pages_va, npages);
if (!gmi->pages_va)
return -ENOMEM;
- gmi->pages_dma = kvcalloc(npages, sizeof(*gmi->pages_dma), GFP_KERNEL);
+ gmi->pages_dma = kvzalloc_objs(*gmi->pages_dma, npages);
if (!gmi->pages_dma)
goto free_va;
@@ -825,7 +825,7 @@ int mana_schedule_serv_work(struct gdma_context *gc, enum gdma_eqe_type type)
return -ENODEV;
}
- mns_wk = kzalloc(sizeof(*mns_wk), GFP_ATOMIC);
+ mns_wk = kzalloc_obj(*mns_wk, GFP_ATOMIC);
if (!mns_wk) {
module_put(THIS_MODULE);
clear_bit(GC_IN_SERVICE, &gc->flags);
@@ -1991,7 +1991,7 @@ struct gdma_irq_context *mana_gd_get_gic(struct gdma_context *gc,
*msi_requested = msi;
}
- gic = kzalloc(sizeof(*gic), GFP_KERNEL);
+ gic = kzalloc_obj(*gic);
if (!gic) {
gic = ERR_PTR(-ENOMEM);
if (irq_map.virq)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_bpf.c b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
index 53308e139cbe..5c9961ee9747 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_bpf.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
@@ -208,6 +208,7 @@ static int mana_xdp_set(struct net_device *ndev, struct bpf_prog *prog,
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"XDP: Insufficient memory for tx/rx re-config");
+ apc->bpf_prog = old_prog;
return err;
}
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 7a1ac853e3ab..591fb4191d90 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2986,6 +2986,10 @@ static int mana_alloc_rx_wqe(struct mana_port_context *apc,
*cq_size += COMP_ENTRY_SIZE;
}
+ /* Reserve an extra slot for Fence completion
+ * event (CQE_RX_OBJECT_FENCE) in case RX CQ is full.
+ */
+ *cq_size += COMP_ENTRY_SIZE;
return 0;
}
@@ -3080,7 +3084,7 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
goto out;
rq_size = MANA_PAGE_ALIGN(rq_size);
- cq_size = MANA_PAGE_ALIGN(cq_size);
+ cq_size = MANA_PAGE_ALIGN(roundup_pow_of_two(cq_size));
/* Create RQ */
memset(&spec, 0, sizeof(spec));
@@ -3983,7 +3987,8 @@ static void mana_rdma_service_handle(struct work_struct *work)
struct device *dev = gd->gdma_context->dev;
int ret;
- if (READ_ONCE(gd->rdma_teardown))
+ /* Pairs with the smp_store_release() in mana_rdma_probe(). */
+ if (smp_load_acquire(&gd->rdma_teardown))
goto out;
switch (serv_work->event) {
@@ -4279,6 +4284,21 @@ int mana_rdma_probe(struct gdma_dev *gd)
if (err)
return err;
+ /* Clear the state left by a previous mana_rdma_remove() so servicing
+ * events are handled again after a reset cycle.
+ */
+ gd->is_suspended = false;
+
+ /* Publish is_suspended before re-opening the gate, so the handler
+ * cannot observe an open gate with a stale is_suspended. Pairs
+ * with the smp_load_acquire() in mana_rdma_service_handle(). This
+ * matters on the reset path, where mana_rdma_remove() closed the
+ * gate and drained the workqueue; on the initial probe path the
+ * gate was never closed and both flags are already clear. It does
+ * not order gd->adev, which add_adev() publishes below.
+ */
+ smp_store_release(&gd->rdma_teardown, false);
+
err = add_adev(gd, "rdma");
if (err)
mana_gd_deregister_device(gd);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
index a2a89d48e3ca..4e83637715e0 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
@@ -1421,7 +1421,8 @@ static int nfp_net_get_fs_rule(struct nfp_net *nn, struct ethtool_rxnfc *cmd)
return -ENOENT;
}
-static int nfp_net_get_fs_loc(struct nfp_net *nn, u32 *rule_locs)
+static int nfp_net_get_fs_loc(struct nfp_net *nn, struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
{
struct nfp_fs_entry *entry;
u32 count = 0;
@@ -1429,8 +1430,12 @@ static int nfp_net_get_fs_loc(struct nfp_net *nn, u32 *rule_locs)
if (!(nn->cap_w1 & NFP_NET_CFG_CTRL_FLOW_STEER))
return -EOPNOTSUPP;
- list_for_each_entry(entry, &nn->fs.list, node)
+ list_for_each_entry(entry, &nn->fs.list, node) {
+ if (count == cmd->rule_cnt)
+ return -EMSGSIZE;
rule_locs[count++] = entry->loc;
+ }
+ cmd->rule_cnt = count;
return 0;
}
@@ -1455,7 +1460,7 @@ static int nfp_net_get_rxnfc(struct net_device *netdev,
return nfp_net_get_fs_rule(nn, cmd);
case ETHTOOL_GRXCLSRLALL:
cmd->data = NFP_FS_MAX_ENTRY;
- return nfp_net_get_fs_loc(nn, rule_locs);
+ return nfp_net_get_fs_loc(nn, cmd, rule_locs);
default:
return -EOPNOTSUPP;
}
@@ -1698,8 +1703,14 @@ static int nfp_net_fs_add(struct nfp_net *nn, struct ethtool_rxnfc *cmd)
nn->fs.count--;
err = nfp_net_fs_add_hw(nn, new);
- if (err)
+ if (err) {
+ /* mbox broken, adding the old rule back will
+ * likely also fail.
+ */
+ list_del(&entry->node);
+ kfree(entry);
goto err;
+ }
nn->fs.count++;
list_replace(&entry->node, &new->node);
diff --git a/drivers/net/ethernet/oa_tc6.c b/drivers/net/ethernet/oa_tc6.c
index 417c15d1ff42..6fcc5f561d56 100644
--- a/drivers/net/ethernet/oa_tc6.c
+++ b/drivers/net/ethernet/oa_tc6.c
@@ -83,7 +83,7 @@ struct oa_tc6 {
u16 spi_data_tx_buf_offset;
u16 tx_credits;
u8 rx_chunks_available;
- bool rx_buf_overflow;
+ bool wait_until_start_valid;
bool int_flag;
bool disable_traffic;
bool prot_ctrl;
@@ -455,7 +455,7 @@ static int oa_tc6_mdiobus_read(struct mii_bus *bus, int addr, int regnum)
{
struct oa_tc6 *tc6 = bus->priv;
u32 regval;
- bool ret;
+ int ret;
ret = oa_tc6_read_register(tc6, OA_TC6_PHY_STD_REG_ADDR_BASE |
(regnum & OA_TC6_PHY_STD_REG_ADDR_MASK),
@@ -693,6 +693,26 @@ static int oa_tc6_enable_data_transfer(struct oa_tc6 *tc6)
return oa_tc6_write_register(tc6, OA_TC6_REG_CONFIG0, value);
}
+/* Called when a frame that is meant to be transmitted, is dropped. */
+static void oa_tc6_drop_tx_skb(struct oa_tc6 *tc6, struct sk_buff *skb)
+{
+ if (skb) {
+ tc6->netdev->stats.tx_dropped++;
+ dev_kfree_skb_any(skb);
+ }
+}
+
+static struct sk_buff *oa_tc6_detach_waiting_tx_skb(struct oa_tc6 *tc6)
+{
+ struct sk_buff *skb;
+
+ lockdep_assert_held(&tc6->tx_skb_lock);
+ skb = tc6->waiting_tx_skb;
+ tc6->waiting_tx_skb = NULL;
+
+ return skb;
+}
+
static void oa_tc6_cleanup_ongoing_rx_skb(struct oa_tc6 *tc6)
{
if (tc6->rx_skb) {
@@ -704,29 +724,39 @@ static void oa_tc6_cleanup_ongoing_rx_skb(struct oa_tc6 *tc6)
static void oa_tc6_cleanup_ongoing_tx_skb(struct oa_tc6 *tc6)
{
- if (tc6->ongoing_tx_skb) {
- tc6->netdev->stats.tx_dropped++;
- kfree_skb(tc6->ongoing_tx_skb);
- tc6->ongoing_tx_skb = NULL;
- }
+ oa_tc6_drop_tx_skb(tc6, tc6->ongoing_tx_skb);
+ tc6->ongoing_tx_skb = NULL;
}
static void oa_tc6_cleanup_waiting_tx_skb(struct oa_tc6 *tc6)
{
- if (tc6->waiting_tx_skb) {
- tc6->netdev->stats.tx_dropped++;
- kfree_skb(tc6->waiting_tx_skb);
- tc6->waiting_tx_skb = NULL;
- }
+ struct sk_buff *skb;
+
+ spin_lock_bh(&tc6->tx_skb_lock);
+ skb = oa_tc6_detach_waiting_tx_skb(tc6);
+ spin_unlock_bh(&tc6->tx_skb_lock);
+
+ oa_tc6_drop_tx_skb(tc6, skb);
}
-static void oa_tc6_free_pending_skbs(struct oa_tc6 *tc6)
+static void oa_tc6_free_ongoing_skbs(struct oa_tc6 *tc6)
{
oa_tc6_cleanup_ongoing_tx_skb(tc6);
oa_tc6_cleanup_ongoing_rx_skb(tc6);
+}
+
+static void oa_tc6_free_pending_skbs(struct oa_tc6 *tc6)
+{
+ oa_tc6_free_ongoing_skbs(tc6);
oa_tc6_cleanup_waiting_tx_skb(tc6);
}
+static void oa_tc6_look_for_new_frame(struct oa_tc6 *tc6)
+{
+ tc6->wait_until_start_valid = true;
+ oa_tc6_cleanup_ongoing_rx_skb(tc6);
+}
+
/* If the failure is at SPI interface level, masking and clearing
* the interrupt of the device won't work. Since SPI interrupt is
* disabled, it should stop the repeated interrupts.
@@ -734,9 +764,19 @@ static void oa_tc6_free_pending_skbs(struct oa_tc6 *tc6)
static void oa_tc6_disable_traffic(struct oa_tc6 *tc6)
{
u32 regval = OA_TC6_INT_MASK0_ALL_INTERRUPTS;
+ struct sk_buff *skb;
+ spin_lock_bh(&tc6->tx_skb_lock);
tc6->disable_traffic = true;
- oa_tc6_free_pending_skbs(tc6);
+ skb = oa_tc6_detach_waiting_tx_skb(tc6);
+ spin_unlock_bh(&tc6->tx_skb_lock);
+
+ /* disable_traffic, when set, is a point of no return to
+ * working state. Keeping the TX queues disabled.
+ */
+ netif_tx_disable(tc6->netdev);
+ oa_tc6_drop_tx_skb(tc6, skb);
+ oa_tc6_free_ongoing_skbs(tc6);
oa_tc6_write_register(tc6, OA_TC6_REG_INT_MASK0, regval);
oa_tc6_read_register(tc6, OA_TC6_REG_STATUS0, &regval);
oa_tc6_write_register(tc6, OA_TC6_REG_STATUS0, regval);
@@ -755,6 +795,13 @@ static int oa_tc6_process_extended_status(struct oa_tc6 *tc6)
return ret;
}
+ /* This function is called for each chunk received in a given SPI
+ * transaction. In case, extended status bit is set in more than
+ * one chunk, skip the write, if status0 is already cleared.
+ */
+ if (!value)
+ return 0;
+
/* Clear the error interrupts status */
ret = oa_tc6_write_register(tc6, OA_TC6_REG_STATUS0, value);
if (ret) {
@@ -764,8 +811,7 @@ static int oa_tc6_process_extended_status(struct oa_tc6 *tc6)
}
if (FIELD_GET(OA_TC6_STATUS0_RX_BUFFER_OVERFLOW_ERROR, value)) {
- tc6->rx_buf_overflow = true;
- oa_tc6_cleanup_ongoing_rx_skb(tc6);
+ oa_tc6_look_for_new_frame(tc6);
net_err_ratelimited("%s: Receive buffer overflow error\n",
tc6->netdev->name);
return -EAGAIN;
@@ -791,6 +837,8 @@ static int oa_tc6_process_extended_status(struct oa_tc6 *tc6)
static int oa_tc6_process_rx_chunk_footer(struct oa_tc6 *tc6, u32 footer)
{
+ int ret = 0;
+
/* Process rx chunk footer for the following,
* 1. tx credits
* 2. errors if any from MAC-PHY
@@ -801,9 +849,11 @@ static int oa_tc6_process_rx_chunk_footer(struct oa_tc6 *tc6, u32 footer)
footer);
if (FIELD_GET(OA_TC6_DATA_FOOTER_EXTENDED_STS, footer)) {
- int ret = oa_tc6_process_extended_status(tc6);
-
- if (ret)
+ ret = oa_tc6_process_extended_status(tc6);
+ /* EAGAIN error is recoverable. Move on to check
+ * HEADER and SYNC errors before returning.
+ */
+ if (ret && ret != -EAGAIN)
return ret;
}
@@ -821,7 +871,7 @@ static int oa_tc6_process_rx_chunk_footer(struct oa_tc6 *tc6, u32 footer)
return -ENODEV;
}
- return 0;
+ return ret;
}
static void oa_tc6_submit_rx_skb(struct oa_tc6 *tc6)
@@ -846,13 +896,35 @@ static void oa_tc6_submit_rx_skb(struct oa_tc6 *tc6)
tc6->rx_skb = NULL;
}
-static void oa_tc6_update_rx_skb(struct oa_tc6 *tc6, u8 *payload, u8 length)
+/* On oversubscribed traffic condition, particularly with overwhelming rx
+ * buffer overflow errors, there could be data chunk loss. If tail + length
+ * goes beyond end pointer, that is an indication that the data chunk with
+ * end_valid bit is lost. Time to look for a data chunk with start_valid bit.
+ *
+ * If rx_skb is NULL, it is time to start looking for data chunk with
+ * start_bit.
+ */
+static int oa_tc6_update_rx_skb(struct oa_tc6 *tc6, u8 *payload, u8 length)
{
+ if (!tc6->rx_skb ||
+ skb_tailroom(tc6->rx_skb) < length) {
+ oa_tc6_look_for_new_frame(tc6);
+ return -EAGAIN;
+ }
+
memcpy(skb_put(tc6->rx_skb, length), payload, length);
+ return 0;
}
+/* On overwhelming rx buffer overflow errors, due to data chunk loss, it is
+ * possible that we get two data chunks with start_valid bit set, without
+ * end_valid bit set in between. In this case, rx_skb would have a valid
+ * buffer pointer. We should release, if a valid pointer is found before
+ * allocating a new one.
+ */
static int oa_tc6_allocate_rx_skb(struct oa_tc6 *tc6)
{
+ oa_tc6_cleanup_ongoing_rx_skb(tc6);
tc6->rx_skb = netdev_alloc_skb_ip_align(tc6->netdev, tc6->netdev->mtu +
ETH_HLEN + ETH_FCS_LEN);
if (!tc6->rx_skb) {
@@ -872,7 +944,9 @@ static int oa_tc6_prcs_complete_rx_frame(struct oa_tc6 *tc6, u8 *payload,
if (ret)
return ret;
- oa_tc6_update_rx_skb(tc6, payload, size);
+ ret = oa_tc6_update_rx_skb(tc6, payload, size);
+ if (ret)
+ return ret;
oa_tc6_submit_rx_skb(tc6);
@@ -887,22 +961,24 @@ static int oa_tc6_prcs_rx_frame_start(struct oa_tc6 *tc6, u8 *payload, u16 size)
if (ret)
return ret;
- oa_tc6_update_rx_skb(tc6, payload, size);
-
- return 0;
+ return oa_tc6_update_rx_skb(tc6, payload, size);
}
-static void oa_tc6_prcs_rx_frame_end(struct oa_tc6 *tc6, u8 *payload, u16 size)
+static int oa_tc6_prcs_rx_frame_end(struct oa_tc6 *tc6, u8 *payload, u16 size)
{
- oa_tc6_update_rx_skb(tc6, payload, size);
+ int ret;
- oa_tc6_submit_rx_skb(tc6);
+ ret = oa_tc6_update_rx_skb(tc6, payload, size);
+ if (!ret)
+ oa_tc6_submit_rx_skb(tc6);
+ return ret;
}
-static void oa_tc6_prcs_ongoing_rx_frame(struct oa_tc6 *tc6, u8 *payload,
- u32 footer)
+static int oa_tc6_prcs_ongoing_rx_frame(struct oa_tc6 *tc6, u8 *payload,
+ u32 footer)
{
- oa_tc6_update_rx_skb(tc6, payload, OA_TC6_CHUNK_PAYLOAD_SIZE);
+ return oa_tc6_update_rx_skb(tc6, payload,
+ OA_TC6_CHUNK_PAYLOAD_SIZE);
}
static int oa_tc6_prcs_rx_chunk_payload(struct oa_tc6 *tc6, u8 *data,
@@ -917,10 +993,10 @@ static int oa_tc6_prcs_rx_chunk_payload(struct oa_tc6 *tc6, u8 *data,
u16 size;
/* Restart the new rx frame after receiving rx buffer overflow error */
- if (start_valid && tc6->rx_buf_overflow)
- tc6->rx_buf_overflow = false;
+ if (start_valid && tc6->wait_until_start_valid)
+ tc6->wait_until_start_valid = false;
- if (tc6->rx_buf_overflow)
+ if (tc6->wait_until_start_valid)
return 0;
/* Process the chunk with complete rx frame */
@@ -942,8 +1018,7 @@ static int oa_tc6_prcs_rx_chunk_payload(struct oa_tc6 *tc6, u8 *data,
/* Process the chunk with only rx frame end */
if (end_valid && !start_valid) {
size = end_byte_offset + 1;
- oa_tc6_prcs_rx_frame_end(tc6, data, size);
- return 0;
+ return oa_tc6_prcs_rx_frame_end(tc6, data, size);
}
/* Process the chunk with previous rx frame end and next rx frame
@@ -957,6 +1032,15 @@ static int oa_tc6_prcs_rx_chunk_payload(struct oa_tc6 *tc6, u8 *data,
if (tc6->rx_skb) {
size = end_byte_offset + 1;
oa_tc6_prcs_rx_frame_end(tc6, data, size);
+
+ /* Return value from oa_tc6_prcs_rx_frame_end is not
+ * checked. If it returned an error, it is to make
+ * the code to look for new frame. At this stage,
+ * code below is going to process a new frame. So,
+ * error condition is set to false, in case it is
+ * set before proceeding.
+ */
+ tc6->wait_until_start_valid = false;
}
size = OA_TC6_CHUNK_PAYLOAD_SIZE - start_byte_offset;
return oa_tc6_prcs_rx_frame_start(tc6,
@@ -965,9 +1049,7 @@ static int oa_tc6_prcs_rx_chunk_payload(struct oa_tc6 *tc6, u8 *data,
}
/* Process the chunk with ongoing rx frame data */
- oa_tc6_prcs_ongoing_rx_frame(tc6, data, footer);
-
- return 0;
+ return oa_tc6_prcs_ongoing_rx_frame(tc6, data, footer);
}
static u32 oa_tc6_get_rx_chunk_footer(struct oa_tc6 *tc6, u16 footer_offset)
@@ -983,8 +1065,9 @@ static u32 oa_tc6_get_rx_chunk_footer(struct oa_tc6 *tc6, u16 footer_offset)
static int oa_tc6_process_spi_data_rx_buf(struct oa_tc6 *tc6, u16 length)
{
u16 no_of_rx_chunks = length / OA_TC6_CHUNK_SIZE;
+ bool retry = false;
+ int ret = 0;
u32 footer;
- int ret;
/* All the rx chunks in the receive SPI data buffer are examined here */
for (int i = 0; i < no_of_rx_chunks; i++) {
@@ -993,8 +1076,11 @@ static int oa_tc6_process_spi_data_rx_buf(struct oa_tc6 *tc6, u16 length)
OA_TC6_CHUNK_PAYLOAD_SIZE);
ret = oa_tc6_process_rx_chunk_footer(tc6, footer);
- if (ret)
- return ret;
+ if (ret) {
+ if (ret != -EAGAIN)
+ return ret;
+ retry = true;
+ }
/* If there is a data valid chunks then process it for the
* information needed to determine the validity and the location
@@ -1006,12 +1092,35 @@ static int oa_tc6_process_spi_data_rx_buf(struct oa_tc6 *tc6, u16 length)
ret = oa_tc6_prcs_rx_chunk_payload(tc6, payload,
footer);
- if (ret)
- return ret;
+ if (ret) {
+ if (ret != -ENOMEM && ret != -EAGAIN)
+ return ret;
+ retry = true;
+ }
}
}
- return 0;
+ /* Not bailing out on recoverable error codes, -EAGAIN and
+ * -ENOMEM. If subsequent loop iterations, if any, succeeds,
+ * error code would be overwritten. retry flag helps to
+ * make the caller to continue and retry. Since recovery
+ * action for -ENOMEM and -EAGAIN are same, we are returning
+ * one of the error codes, that is -EAGAIN.
+ *
+ * Successful recovery depends on how small the frames are,
+ * how many chunks, among the received chunks triggered the
+ * error, whether data is intact even with error conditions.
+ * As a result, there is no single, best method to recover
+ * most data when error conditions hit. We do our best by
+ * processing all the chunks with good "footer header" and
+ * "data valid" bit set.
+ */
+ if (retry) {
+ ret = -EAGAIN;
+ oa_tc6_look_for_new_frame(tc6);
+ }
+
+ return ret;
}
static __be32 oa_tc6_prepare_data_header(bool data_valid, bool start_valid,
@@ -1173,12 +1282,9 @@ static int oa_tc6_try_spi_transfer(struct oa_tc6 *tc6)
}
ret = oa_tc6_process_spi_data_rx_buf(tc6, spi_len);
- if (ret) {
- if (ret == -EAGAIN)
- continue;
- oa_tc6_cleanup_ongoing_tx_skb(tc6);
- oa_tc6_cleanup_ongoing_rx_skb(tc6);
+ if (ret && ret != -EAGAIN) {
+ oa_tc6_free_ongoing_skbs(tc6);
netdev_err(tc6->netdev, "Device error: %d\n", ret);
return ret;
}
@@ -1200,15 +1306,20 @@ static irqreturn_t oa_tc6_macphy_threaded_irq(int irq, void *data)
* no need to attempt spi transfer, once it fails. Pending skbs
* are already freed.
*/
- if (!tc6->disable_traffic) {
- while (tc6->int_flag ||
- (tc6->waiting_tx_skb && tc6->tx_credits)) {
- ret = oa_tc6_try_spi_transfer(tc6);
- if (ret) {
- disable_irq_nosync(tc6->spi->irq);
- oa_tc6_disable_traffic(tc6);
- break;
- }
+ spin_lock_bh(&tc6->tx_skb_lock);
+ if (tc6->disable_traffic) {
+ spin_unlock_bh(&tc6->tx_skb_lock);
+ return IRQ_HANDLED;
+ }
+ spin_unlock_bh(&tc6->tx_skb_lock);
+
+ while (tc6->int_flag ||
+ (tc6->waiting_tx_skb && tc6->tx_credits)) {
+ ret = oa_tc6_try_spi_transfer(tc6);
+ if (ret) {
+ disable_irq_nosync(tc6->spi->irq);
+ oa_tc6_disable_traffic(tc6);
+ break;
}
}
@@ -1287,23 +1398,30 @@ EXPORT_SYMBOL_GPL(oa_tc6_zero_align_receive_frame_enable);
* @tc6: oa_tc6 struct.
* @skb: socket buffer in which the ethernet frame is stored.
*
- * Return: NETDEV_TX_OK if the transmit ethernet frame skb added in the tx_skb_q
- * otherwise returns NETDEV_TX_BUSY.
+ * Return: NETDEV_TX_OK either on successful queueing of the packet for
+ * transmission, or on packet getting dropped. Packet can be dropped due to
+ * failure in linearizing the buffer or disable_traffic is set due to
+ * earlier fatal error. Returns NETDEV_TX_BUSY when there is no room
+ * to queue the packet.
*/
netdev_tx_t oa_tc6_start_xmit(struct oa_tc6 *tc6, struct sk_buff *skb)
{
- if (tc6->disable_traffic || tc6->waiting_tx_skb) {
- netif_stop_queue(tc6->netdev);
- return NETDEV_TX_BUSY;
- }
-
if (skb_linearize(skb)) {
- dev_kfree_skb_any(skb);
- tc6->netdev->stats.tx_dropped++;
+ oa_tc6_drop_tx_skb(tc6, skb);
return NETDEV_TX_OK;
}
spin_lock_bh(&tc6->tx_skb_lock);
+ if (tc6->waiting_tx_skb) {
+ netif_stop_queue(tc6->netdev);
+ spin_unlock_bh(&tc6->tx_skb_lock);
+ return NETDEV_TX_BUSY;
+ }
+ if (tc6->disable_traffic) {
+ spin_unlock_bh(&tc6->tx_skb_lock);
+ oa_tc6_drop_tx_skb(tc6, skb);
+ return NETDEV_TX_OK;
+ }
tc6->waiting_tx_skb = skb;
spin_unlock_bh(&tc6->tx_skb_lock);
@@ -1462,8 +1580,10 @@ EXPORT_SYMBOL_GPL(oa_tc6_init);
*/
void oa_tc6_exit(struct oa_tc6 *tc6)
{
- tc6->disable_traffic = true;
disable_irq(tc6->spi->irq);
+ spin_lock_bh(&tc6->tx_skb_lock);
+ tc6->disable_traffic = true;
+ spin_unlock_bh(&tc6->tx_skb_lock);
oa_tc6_phy_exit(tc6);
oa_tc6_free_pending_skbs(tc6);
}
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
index e436e3231e86..2543a8ff8547 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
@@ -1672,15 +1672,22 @@ static int ionic_tx(struct net_device *netdev, struct ionic_queue *q,
stats->pkts++;
stats->bytes += skb->len;
+ ionic_txq_post(q, false);
+
if (likely(!ionic_txq_hwstamp_enabled(q))) {
struct netdev_queue *ndq = q_to_ndq(netdev, q);
- if (unlikely(!ionic_q_has_space(q, MAX_SKB_FRAGS + 1)))
- netif_tx_stop_queue(ndq);
+ netif_txq_maybe_stop(ndq, ionic_q_space_avail(q),
+ MAX_SKB_FRAGS + 1, MAX_SKB_FRAGS + 1);
ring_dbell = __netdev_tx_sent_queue(ndq, skb->len,
netdev_xmit_more());
}
- ionic_txq_post(q, ring_dbell);
+
+ if (ring_dbell) {
+ ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type,
+ q->dbval | q->head_idx);
+ q->dbell_jiffies = jiffies;
+ }
return 0;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index f2fc89176654..62c3441911e7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3676,6 +3676,14 @@ static int stmmac_hw_setup(struct net_device *dev)
/* Initialize MTL*/
stmmac_mtl_configuration(priv);
+ /* Apply the RX packet parser table */
+ if (priv->tc_entries) {
+ ret = stmmac_rxp_config(priv, priv->hw->pcsr, priv->tc_entries,
+ priv->tc_entries_max);
+ if (ret)
+ return ret;
+ }
+
/* Initialize Safety Features */
stmmac_safety_feat_configuration(priv);
@@ -4319,6 +4327,7 @@ static bool stmmac_vlan_insert(struct stmmac_priv *priv, struct sk_buff *skb,
/**
* stmmac_tso_allocator - close entry point of the driver
* @priv: driver private structure
+ * @entry: TX queue buffer index
* @des: buffer start address
* @total_len: total length to fill in descriptors
* @last_segment: condition for the last descriptor
@@ -4327,8 +4336,9 @@ static bool stmmac_vlan_insert(struct stmmac_priv *priv, struct sk_buff *skb,
* This function fills descriptor and request new descriptors according to
* buffer length to fill
*/
-static void stmmac_tso_allocator(struct stmmac_priv *priv, dma_addr_t des,
- int total_len, bool last_segment, u32 queue)
+static void stmmac_tso_allocator(struct stmmac_priv *priv, u32 *entry,
+ dma_addr_t des, int total_len,
+ bool last_segment, u32 queue)
{
struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue];
struct dma_desc *desc;
@@ -4340,14 +4350,13 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, dma_addr_t des,
while (tmp_len > 0) {
dma_addr_t curr_addr;
- tx_q->cur_tx = STMMAC_NEXT_ENTRY(tx_q->cur_tx,
- priv->dma_conf.dma_tx_size);
- WARN_ON(tx_q->tx_skbuff[tx_q->cur_tx]);
+ *entry = STMMAC_NEXT_ENTRY(*entry, priv->dma_conf.dma_tx_size);
+ WARN_ON(tx_q->tx_skbuff[*entry]);
if (tx_q->tbs & STMMAC_TBS_AVAIL)
- desc = &tx_q->dma_entx[tx_q->cur_tx].basic;
+ desc = &tx_q->dma_entx[*entry].basic;
else
- desc = &tx_q->dma_tx[tx_q->cur_tx];
+ desc = &tx_q->dma_tx[*entry];
curr_addr = des + (total_len - tmp_len);
stmmac_set_desc_addr(priv, desc, curr_addr);
@@ -4445,6 +4454,26 @@ static bool stmmac_tso_valid_packet(struct sk_buff *skb)
header_len + gso_size < 16383;
}
+static int stmmac_tso_get_num_desc(struct stmmac_tx_queue *tx_q,
+ struct sk_buff *skb, u32 pay_len)
+{
+ int i, ndesc = 1;
+
+ /* head payload */
+ ndesc += DIV_ROUND_UP(pay_len, TSO_MAX_BUFF_SIZE);
+ /* frag payload */
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ ndesc += DIV_ROUND_UP(skb_frag_size(frag),
+ TSO_MAX_BUFF_SIZE);
+ }
+ /* MSS update requires a new descriptor */
+ ndesc += !!(skb_shinfo(skb)->gso_size != tx_q->mss);
+
+ return ndesc;
+}
+
/**
* stmmac_tso_xmit - Tx entry point of the driver for oversized frames (TSO)
* @skb : the socket buffer
@@ -4486,12 +4515,12 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct dma_desc *desc, *first, *mss_desc = NULL;
struct stmmac_priv *priv = netdev_priv(dev);
- unsigned int first_entry, tx_packets;
+ unsigned int first_entry, entry, tx_packets;
struct stmmac_txq_stats *txq_stats;
+ int i, first_tx, nfrags, ndesc;
struct stmmac_tx_queue *tx_q;
bool set_ic, is_last_segment;
u32 pay_len, mss, queue;
- int i, first_tx, nfrags;
u8 proto_hdr_len, hdr;
dma_addr_t des;
@@ -4504,14 +4533,15 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
/* Compute header lengths */
proto_hdr_len = stmmac_tso_header_size(skb);
+ pay_len = skb_headlen(skb) - proto_hdr_len; /* no frags */
+
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
hdr = sizeof(struct udphdr);
else
hdr = tcp_hdrlen(skb);
- /* Desc availability based on threshold should be enough safe */
- if (unlikely(stmmac_tx_avail(priv, queue) <
- (((skb->len - proto_hdr_len) / TSO_MAX_BUFF_SIZE + 1)))) {
+ ndesc = stmmac_tso_get_num_desc(tx_q, skb, pay_len);
+ if (unlikely(stmmac_tx_avail(priv, queue) < ndesc)) {
if (!netif_tx_queue_stopped(netdev_get_tx_queue(dev, queue))) {
netif_tx_stop_queue(netdev_get_tx_queue(priv->dev,
queue));
@@ -4523,8 +4553,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
- pay_len = skb_headlen(skb) - proto_hdr_len; /* no frags */
-
mss = skb_shinfo(skb)->gso_size;
/* set new MSS value if needed */
@@ -4549,22 +4577,24 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
}
first_entry = tx_q->cur_tx;
- WARN_ON(tx_q->tx_skbuff[first_entry]);
+ entry = first_entry;
+
+ WARN_ON(tx_q->tx_skbuff[entry]);
if (tx_q->tbs & STMMAC_TBS_AVAIL)
- desc = &tx_q->dma_entx[first_entry].basic;
+ desc = &tx_q->dma_entx[entry].basic;
else
- desc = &tx_q->dma_tx[first_entry];
+ desc = &tx_q->dma_tx[entry];
first = desc;
/* first descriptor: fill Headers on Buf1 */
des = dma_map_single(priv->device, skb->data, skb_headlen(skb),
DMA_TO_DEVICE);
if (dma_mapping_error(priv->device, des))
- goto dma_map_err;
+ goto error;
stmmac_set_desc_addr(priv, first, des);
- stmmac_tso_allocator(priv, des + proto_hdr_len, pay_len,
+ stmmac_tso_allocator(priv, &entry, des + proto_hdr_len, pay_len,
(nfrags == 0), queue);
/* In case two or more DMA transmit descriptors are allocated for this
@@ -4579,8 +4609,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
* this DMA buffer right after the DMA engine completely finishes the
* full buffer transmission.
*/
- stmmac_set_tx_skb_dma_entry(tx_q, tx_q->cur_tx, des, skb_headlen(skb),
- false);
+ stmmac_set_tx_skb_dma_entry(tx_q, entry, des, skb_headlen(skb), false);
/* Prepare fragments */
for (i = 0; i < nfrags; i++) {
@@ -4590,14 +4619,15 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
skb_frag_size(frag),
DMA_TO_DEVICE);
if (dma_mapping_error(priv->device, des))
- goto dma_map_err;
+ goto error_dma_unmap;
- stmmac_tso_allocator(priv, des, skb_frag_size(frag),
+ stmmac_tso_allocator(priv, &entry, des, skb_frag_size(frag),
(i == nfrags - 1), queue);
- stmmac_set_tx_skb_dma_entry(tx_q, tx_q->cur_tx, des,
+ stmmac_set_tx_skb_dma_entry(tx_q, entry, des,
skb_frag_size(frag), true);
}
+ tx_q->cur_tx = entry;
stmmac_set_tx_dma_last_segment(tx_q, tx_q->cur_tx);
@@ -4702,7 +4732,19 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
-dma_map_err:
+error_dma_unmap:
+ for (;;) {
+ desc = stmmac_get_tx_desc(priv, tx_q, first_entry);
+ stmmac_release_tx_desc(priv, desc, priv->descriptor_mode);
+ stmmac_free_tx_buffer(priv, &priv->dma_conf, queue,
+ first_entry);
+ if (first_entry == entry)
+ break;
+
+ first_entry = STMMAC_NEXT_ENTRY(first_entry,
+ priv->dma_conf.dma_tx_size);
+ }
+error:
dev_err(priv->device, "Tx dma map failed\n");
dev_kfree_skb(skb);
priv->xstats.tx_dropped++;
@@ -8002,6 +8044,7 @@ static int __stmmac_dvr_probe(struct device *device,
stmmac_napi_add(ndev);
mutex_init(&priv->lock);
+ rwlock_init(&priv->ptp_lock);
stmmac_fpe_init(priv);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
index 960249960004..3bfcc9760dce 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
@@ -365,7 +365,6 @@ void stmmac_ptp_register(struct stmmac_priv *priv)
if (priv->plat->crosststamp)
priv->ptp_clock_ops.getcrosststamp = stmmac_getcrosststamp;
- rwlock_init(&priv->ptp_lock);
mutex_init(&priv->aux_ts_lock);
priv->ptp_clock = ptp_clock_register(&priv->ptp_clock_ops,
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 298efc76a56b..69fe5717846b 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -318,6 +318,11 @@ static int gtp_inner_proto(struct sk_buff *skb, unsigned int hdrlen,
static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb,
unsigned int hdrlen, unsigned int role, __u16 inner_proto)
{
+ if (skb_is_gso(skb)) {
+ netdev_dbg(pctx->dev, "GSO is not supported in GTP\n");
+ goto err;
+ }
+
if (!gtp_check_ms(skb, pctx, hdrlen, role, inner_proto)) {
netdev_dbg(pctx->dev, "No PDP ctx for this MS\n");
return 1;
diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c
index 2b7034193a00..abfcfe07246a 100644
--- a/drivers/net/ieee802154/cc2520.c
+++ b/drivers/net/ieee802154/cc2520.c
@@ -1156,11 +1156,10 @@ static void cc2520_remove(struct spi_device *spi)
{
struct cc2520_private *priv = spi_get_drvdata(spi);
- mutex_destroy(&priv->buffer_mutex);
- flush_work(&priv->fifop_irqwork);
-
+ disable_work_sync(&priv->fifop_irqwork);
ieee802154_unregister_hw(priv->hw);
ieee802154_free_hw(priv->hw);
+ mutex_destroy(&priv->buffer_mutex);
}
static const struct spi_device_id cc2520_ids[] = {
diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index 6daa0f198b9f..a9bd1555d2dc 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -72,6 +72,8 @@ struct hwsim_phy {
struct ieee802154_hw *hw;
u32 idx;
+ /* Serializes phy->pib_updates. */
+ spinlock_t pib_lock;
struct hwsim_pib __rcu *pib;
bool suspended;
@@ -102,8 +104,6 @@ static int hwsim_update_pib(struct ieee802154_hw *hw, u8 page, u8 channel,
if (!pib)
return -ENOMEM;
- pib_old = rtnl_dereference(phy->pib);
-
pib->page = page;
pib->channel = channel;
pib->filt.short_addr = filt->short_addr;
@@ -112,7 +112,10 @@ static int hwsim_update_pib(struct ieee802154_hw *hw, u8 page, u8 channel,
pib->filt.pan_coord = filt->pan_coord;
pib->filt_level = filt_level;
- rcu_assign_pointer(phy->pib, pib);
+ spin_lock_bh(&phy->pib_lock);
+ pib_old = rcu_replace_pointer(phy->pib, pib,
+ lockdep_is_held(&phy->pib_lock));
+ spin_unlock_bh(&phy->pib_lock);
kfree_rcu(pib_old, rcu);
return 0;
}
@@ -952,6 +955,7 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
goto err_pib;
}
+ spin_lock_init(&phy->pib_lock);
pib->channel = 13;
pib->filt.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
pib->filt.pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 4939cf67b336..f29864db662a 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -848,7 +848,6 @@ static int ipvlan_device_event(struct notifier_block *unused,
__ipvlan_link_delete(net, ipvlan->dev, &lst_kill);
}
- unregister_netdevice_many(&lst_kill);
break;
}
case NETDEV_FEAT_CHANGE:
@@ -899,6 +898,9 @@ static int ipvlan_device_event(struct notifier_block *unused,
mutex_unlock(&port->pnodes_lock);
+ /* Avoid invoking nested netdevice notifiers under pnodes_lock. */
+ unregister_netdevice_many(&lst_kill);
+
ipvlan_port_put(port);
return ret;
diff --git a/drivers/net/mctp/mctp-i3c.c b/drivers/net/mctp/mctp-i3c.c
index 88d9e36cd4a2..4e857dd5df64 100644
--- a/drivers/net/mctp/mctp-i3c.c
+++ b/drivers/net/mctp/mctp-i3c.c
@@ -288,6 +288,7 @@ err:
static int mctp_i3c_probe(struct i3c_device *i3c)
{
struct mctp_i3c_bus *b = NULL, *mbus = NULL;
+ int rc;
/* Look for a known bus */
mutex_lock(&busdevs_lock);
@@ -296,14 +297,16 @@ static int mctp_i3c_probe(struct i3c_device *i3c)
mbus = b;
break;
}
- mutex_unlock(&busdevs_lock);
if (!mbus) {
/* probably no "mctp-controller" property on the i3c bus */
- return -ENODEV;
+ rc = -ENODEV;
+ } else {
+ rc = mctp_i3c_add_device(mbus, i3c);
}
+ mutex_unlock(&busdevs_lock);
- return mctp_i3c_add_device(mbus, i3c);
+ return rc;
}
static void mctp_i3c_remove_device(struct mctp_i3c_device *mi)
diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c
index 3f7d31033bae..1b5213e87070 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -675,7 +675,7 @@ static int net_failover_slave_name_change(struct net_device *slave_dev,
/* We need to bring up the slave after the rename by udev in case
* open failed with EBUSY when it was registered.
*/
- dev_open(slave_dev, NULL);
+ netif_open(slave_dev, NULL);
return 0;
}
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
index 9c171697e762..7a0d5e892a1a 100644
--- a/drivers/net/ntb_netdev.c
+++ b/drivers/net/ntb_netdev.c
@@ -127,8 +127,10 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
{
struct ntb_netdev_queue *q = qp_data;
struct ntb_netdev *dev = q->ntdev;
+ struct pcpu_sw_netstats *tstats;
struct sk_buff *skb, *new_skb;
struct net_device *ndev;
+ unsigned long flags;
int rc;
ndev = dev->ndev;
@@ -139,17 +141,20 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
netdev_dbg(ndev, "%s: %d byte payload received\n", __func__, len);
if (len < 0) {
- ndev->stats.rx_errors++;
- ndev->stats.rx_length_errors++;
+ DEV_STATS_INC(ndev, rx_errors);
+ DEV_STATS_INC(ndev, rx_length_errors);
goto enqueue_again;
}
- ndev->stats.rx_packets++;
- ndev->stats.rx_bytes += len;
+ tstats = this_cpu_ptr(ndev->tstats);
+ flags = u64_stats_update_begin_irqsave(&tstats->syncp);
+ u64_stats_inc(&tstats->rx_packets);
+ u64_stats_add(&tstats->rx_bytes, len);
+ u64_stats_update_end_irqrestore(&tstats->syncp, flags);
new_skb = netdev_alloc_skb(ndev, ndev->mtu + ETH_HLEN);
if (!new_skb) {
- ndev->stats.rx_dropped++;
+ DEV_STATS_INC(ndev, rx_dropped);
goto enqueue_again;
}
@@ -166,8 +171,8 @@ enqueue_again:
rc = ntb_transport_rx_enqueue(qp, skb, skb->data, ndev->mtu + ETH_HLEN);
if (rc) {
dev_kfree_skb_any(skb);
- ndev->stats.rx_errors++;
- ndev->stats.rx_fifo_errors++;
+ DEV_STATS_INC(ndev, rx_errors);
+ DEV_STATS_INC(ndev, rx_fifo_errors);
}
}
@@ -210,25 +215,39 @@ static void ntb_netdev_tx_handler(struct ntb_transport_qp *qp, void *qp_data,
{
struct ntb_netdev_queue *q = qp_data;
struct ntb_netdev *dev = q->ntdev;
+ struct pcpu_sw_netstats *tstats;
struct net_device *ndev;
struct sk_buff *skb;
+ unsigned long flags;
+ bool registered;
ndev = dev->ndev;
skb = data;
if (!skb || !ndev)
return;
+ rcu_read_lock();
+ registered = READ_ONCE(ndev->reg_state) == NETREG_REGISTERED;
+ if (!registered)
+ goto free_skb;
+
if (len > 0) {
- ndev->stats.tx_packets++;
- ndev->stats.tx_bytes += skb->len;
+ /* The memcpy kthread can migrate, so pin the per-CPU update. */
+ tstats = get_cpu_ptr(ndev->tstats);
+ flags = u64_stats_update_begin_irqsave(&tstats->syncp);
+ u64_stats_inc(&tstats->tx_packets);
+ u64_stats_add(&tstats->tx_bytes, skb->len);
+ u64_stats_update_end_irqrestore(&tstats->syncp, flags);
+ put_cpu_ptr(ndev->tstats);
} else {
- ndev->stats.tx_errors++;
- ndev->stats.tx_aborted_errors++;
+ DEV_STATS_INC(ndev, tx_errors);
+ DEV_STATS_INC(ndev, tx_aborted_errors);
}
+free_skb:
dev_kfree_skb_any(skb);
- if (ntb_transport_tx_free_entry(qp) >= tx_start) {
+ if (registered && ntb_transport_tx_free_entry(qp) >= tx_start) {
/* Make sure anybody stopping the queue after this sees the new
* value of ntb_transport_tx_free_entry()
*/
@@ -237,6 +256,7 @@ static void ntb_netdev_tx_handler(struct ntb_transport_qp *qp, void *qp_data,
ntb_transport_link_query(q->qp))
netif_wake_subqueue(ndev, q->qid);
}
+ rcu_read_unlock();
}
static const struct ntb_queue_handlers ntb_netdev_handlers = {
@@ -277,7 +297,7 @@ static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb,
drop:
dev_kfree_skb_any(skb);
- ndev->stats.tx_dropped++;
+ DEV_STATS_INC(ndev, tx_dropped);
return NETDEV_TX_OK;
}
@@ -639,14 +659,14 @@ static int ntb_netdev_probe(struct device *client_dev)
dev->client_dev = client_dev;
dev->num_queues = 0;
- dev->queues = kzalloc_objs(*dev->queues, NTB_NETDEV_MAX_QUEUES,
- GFP_KERNEL);
+ dev->queues = kzalloc_objs(*dev->queues, NTB_NETDEV_MAX_QUEUES);
if (!dev->queues) {
rc = -ENOMEM;
goto err_free_netdev;
}
ndev->features = NETIF_F_HIGHDMA;
+ ndev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 88255e92b4cd..61a941aa02d9 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -1150,6 +1150,9 @@ static int dp83867_led_polarity_set(struct phy_device *phydev, int index,
case PHY_LED_ACTIVE_LOW:
polarity = 0;
break;
+ case PHY_LED_ACTIVE_HIGH:
+ polarity = DP83867_LED_POLARITY(index);
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/net/phy/dp83td510.c b/drivers/net/phy/dp83td510.c
index d75dae6071ad..9e9a41bf6457 100644
--- a/drivers/net/phy/dp83td510.c
+++ b/drivers/net/phy/dp83td510.c
@@ -439,6 +439,9 @@ static int dp83td510_led_polarity_set(struct phy_device *phydev, int index,
case PHY_LED_ACTIVE_LOW:
polarity = 0;
break;
+ case PHY_LED_ACTIVE_HIGH:
+ polarity = DP83TD510E_LED_POLARITY(index);
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/net/phy/mediatek/mtk-ge.c b/drivers/net/phy/mediatek/mtk-ge.c
index 73d9b72f9d9e..96d8ac5154e5 100644
--- a/drivers/net/phy/mediatek/mtk-ge.c
+++ b/drivers/net/phy/mediatek/mtk-ge.c
@@ -62,10 +62,38 @@ static void mtk_gephy_config_init(struct phy_device *phydev)
FIELD_PREP(MTK_MCC_NEARECHO_OFFSET_MASK, 0x3));
}
+static int mt7530_phy_probe(struct phy_device *phydev)
+{
+ /* The MT7530 internal GE PHY has broken EEE: with EEE advertised,
+ * some link partners fail to establish a stable link (on a 2-pair
+ * cable, 1000BASE-T training fails and the port loops instead of
+ * falling back). MediaTek recommends disabling EEE on this PHY.
+ * Clear the advertisement as early as possible, before anything
+ * can negotiate EEE with the link partner.
+ */
+ return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
+}
+
static int mt7530_phy_config_init(struct phy_device *phydev)
{
+ int ret;
+
mtk_gephy_config_init(phydev);
+ /* The probe() clear alone is not durable: phy_init_hw() replays only
+ * ->config_init after a PHY reset, with the register back at its
+ * EEE-advertising hardware default, and phy_probe() zeroes
+ * eee_disabled_modes (of_set_phy_eee_broken()) after ->probe already
+ * ran. Clear the advertisement again and mark EEE disabled, so that
+ * neither phylib nor userspace can re-enable it; dp83867 disables
+ * broken EEE from config_init() the same way.
+ */
+ ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
+ if (ret)
+ return ret;
+
+ phy_disable_eee(phydev);
+
/* Increase post_update_timer */
phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3,
MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11, 0x4b);
@@ -100,6 +128,7 @@ static struct phy_driver mtk_gephy_driver[] = {
{
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530),
.name = "MediaTek MT7530 PHY",
+ .probe = mt7530_phy_probe,
.config_init = mt7530_phy_config_init,
/* Interrupts are handled by the switch, not the PHY
* itself.
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 3ec3bb439109..a1458da8111b 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1630,8 +1630,10 @@ static void phylink_resolve(struct work_struct *w)
if (pl->phylink_disable_state) {
pl->link_failed = false;
+ link_state = pl->link_config;
link_state.link = false;
} else if (pl->link_failed) {
+ link_state = pl->link_config;
link_state.link = false;
retrigger = true;
} else if (pl->act_link_an_mode == MLO_AN_FIXED) {
diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c
index 583426d06381..6e6e2b944128 100644
--- a/drivers/net/ppp/ppp_async.c
+++ b/drivers/net/ppp/ppp_async.c
@@ -63,8 +63,6 @@ struct asyncppp {
struct tasklet_struct tsk;
- refcount_t refcnt;
- struct completion dead;
struct ppp_channel chan; /* interface to generic ppp layer */
unsigned char obuf[OBUFSIZE];
};
@@ -115,38 +113,6 @@ static const struct ppp_channel_ops async_ops = {
*/
/*
- * We have a potential race on dereferencing tty->disc_data,
- * because the tty layer provides no locking at all - thus one
- * cpu could be running ppp_asynctty_receive while another
- * calls ppp_asynctty_close, which zeroes tty->disc_data and
- * frees the memory that ppp_asynctty_receive is using. The best
- * way to fix this is to use a rwlock in the tty struct, but for now
- * we use a single global rwlock for all ttys in ppp line discipline.
- *
- * FIXME: this is no longer true. The _close path for the ldisc is
- * now guaranteed to be sane.
- */
-static DEFINE_RWLOCK(disc_data_lock);
-
-static struct asyncppp *ap_get(struct tty_struct *tty)
-{
- struct asyncppp *ap;
-
- read_lock(&disc_data_lock);
- ap = tty->disc_data;
- if (ap != NULL)
- refcount_inc(&ap->refcnt);
- read_unlock(&disc_data_lock);
- return ap;
-}
-
-static void ap_put(struct asyncppp *ap)
-{
- if (refcount_dec_and_test(&ap->refcnt))
- complete(&ap->dead);
-}
-
-/*
* Called when a tty is put into PPP line discipline. Called in process
* context.
*/
@@ -180,9 +146,6 @@ ppp_asynctty_open(struct tty_struct *tty)
skb_queue_head_init(&ap->rqueue);
tasklet_setup(&ap->tsk, ppp_async_process);
- refcount_set(&ap->refcnt, 1);
- init_completion(&ap->dead);
-
ap->chan.private = ap;
ap->chan.ops = &async_ops;
ap->chan.mtu = PPP_MRU;
@@ -203,34 +166,18 @@ ppp_asynctty_open(struct tty_struct *tty)
}
/*
- * Called when the tty is put into another line discipline
- * or it hangs up. We have to wait for any cpu currently
- * executing in any of the other ppp_asynctty_* routines to
- * finish before we can call ppp_unregister_channel and free
- * the asyncppp struct. This routine must be called from
- * process context, not interrupt or softirq context.
+ * Called when the tty is put into another line discipline or it hangs up.
+ * This call is serialized against other ldisc functions.
*/
static void
ppp_asynctty_close(struct tty_struct *tty)
{
- struct asyncppp *ap;
+ struct asyncppp *ap = tty->disc_data;
- write_lock_irq(&disc_data_lock);
- ap = tty->disc_data;
- tty->disc_data = NULL;
- write_unlock_irq(&disc_data_lock);
if (!ap)
return;
- /*
- * We have now ensured that nobody can start using ap from now
- * on, but we have to wait for all existing users to finish.
- * Note that ppp_unregister_channel ensures that no calls to
- * our channel ops (i.e. ppp_async_send/ioctl) are in progress
- * by the time it returns.
- */
- if (!refcount_dec_and_test(&ap->refcnt))
- wait_for_completion(&ap->dead);
+ tty->disc_data = NULL;
tasklet_kill(&ap->tsk);
ppp_unregister_channel(&ap->chan);
@@ -241,17 +188,6 @@ ppp_asynctty_close(struct tty_struct *tty)
}
/*
- * Called on tty hangup in process context.
- *
- * Wait for I/O to driver to complete and unregister PPP channel.
- * This is already done by the close routine, so just call that.
- */
-static void ppp_asynctty_hangup(struct tty_struct *tty)
-{
- ppp_asynctty_close(tty);
-}
-
-/*
* Read does nothing - no data is ever available this way.
* Pppd reads and writes packets via /dev/ppp instead.
*/
@@ -281,7 +217,7 @@ ppp_asynctty_write(struct tty_struct *tty, struct file *file, const u8 *buf,
static int
ppp_asynctty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
{
- struct asyncppp *ap = ap_get(tty);
+ struct asyncppp *ap = tty->disc_data;
int err, val;
int __user *p = (int __user *)arg;
@@ -322,7 +258,6 @@ ppp_asynctty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
err = tty_mode_ioctl(tty, cmd, arg);
}
- ap_put(ap);
return err;
}
@@ -331,7 +266,7 @@ static void
ppp_asynctty_receive(struct tty_struct *tty, const u8 *buf, const u8 *cflags,
size_t count)
{
- struct asyncppp *ap = ap_get(tty);
+ struct asyncppp *ap = tty->disc_data;
unsigned long flags;
if (!ap)
@@ -341,21 +276,19 @@ ppp_asynctty_receive(struct tty_struct *tty, const u8 *buf, const u8 *cflags,
spin_unlock_irqrestore(&ap->recv_lock, flags);
if (!skb_queue_empty(&ap->rqueue))
tasklet_schedule(&ap->tsk);
- ap_put(ap);
tty_unthrottle(tty);
}
static void
ppp_asynctty_wakeup(struct tty_struct *tty)
{
- struct asyncppp *ap = ap_get(tty);
+ struct asyncppp *ap = tty->disc_data;
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
if (!ap)
return;
set_bit(XMIT_WAKEUP, &ap->xmit_flags);
tasklet_schedule(&ap->tsk);
- ap_put(ap);
}
@@ -365,7 +298,6 @@ static struct tty_ldisc_ops ppp_ldisc = {
.name = "ppp",
.open = ppp_asynctty_open,
.close = ppp_asynctty_close,
- .hangup = ppp_asynctty_hangup,
.read = ppp_asynctty_read,
.write = ppp_asynctty_write,
.ioctl = ppp_asynctty_ioctl,
@@ -810,11 +742,8 @@ process_input_packet(struct asyncppp *ap)
err:
/* frame had an error, remember that, reset SC_TOSS & SC_ESCAPE */
ap->state = SC_PREV_ERROR;
- if (skb) {
- /* make skb appear as freshly allocated */
- skb_trim(skb, 0);
- skb_reserve(skb, - skb_headroom(skb));
- }
+ kfree_skb(skb);
+ ap->rpkt = NULL;
}
/* Called when the tty driver has data for us. Runs parallel with the
diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c
index 0b1bd1635c39..ebd62a7ab54b 100644
--- a/drivers/net/ppp/ppp_synctty.c
+++ b/drivers/net/ppp/ppp_synctty.c
@@ -38,11 +38,9 @@
#include <linux/ppp-ioctl.h>
#include <linux/ppp_channel.h>
#include <linux/spinlock.h>
-#include <linux/completion.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
-#include <linux/refcount.h>
#include <linux/unaligned.h>
#include <linux/uaccess.h>
@@ -67,8 +65,6 @@ struct syncppp {
struct tasklet_struct tsk;
- refcount_t refcnt;
- struct completion dead_cmp;
struct ppp_channel chan; /* interface to generic ppp layer */
};
@@ -117,37 +113,6 @@ ppp_print_buffer (const char *name, const __u8 *buf, int count)
*/
/*
- * We have a potential race on dereferencing tty->disc_data,
- * because the tty layer provides no locking at all - thus one
- * cpu could be running ppp_synctty_receive while another
- * calls ppp_synctty_close, which zeroes tty->disc_data and
- * frees the memory that ppp_synctty_receive is using. The best
- * way to fix this is to use a rwlock in the tty struct, but for now
- * we use a single global rwlock for all ttys in ppp line discipline.
- *
- * FIXME: Fixed in tty_io nowadays.
- */
-static DEFINE_RWLOCK(disc_data_lock);
-
-static struct syncppp *sp_get(struct tty_struct *tty)
-{
- struct syncppp *ap;
-
- read_lock(&disc_data_lock);
- ap = tty->disc_data;
- if (ap != NULL)
- refcount_inc(&ap->refcnt);
- read_unlock(&disc_data_lock);
- return ap;
-}
-
-static void sp_put(struct syncppp *ap)
-{
- if (refcount_dec_and_test(&ap->refcnt))
- complete(&ap->dead_cmp);
-}
-
-/*
* Called when a tty is put into sync-PPP line discipline.
*/
static int
@@ -177,9 +142,6 @@ ppp_sync_open(struct tty_struct *tty)
skb_queue_head_init(&ap->rqueue);
tasklet_setup(&ap->tsk, ppp_sync_process);
- refcount_set(&ap->refcnt, 1);
- init_completion(&ap->dead_cmp);
-
ap->chan.private = ap;
ap->chan.ops = &sync_ops;
ap->chan.mtu = PPP_MRU;
@@ -201,34 +163,18 @@ ppp_sync_open(struct tty_struct *tty)
}
/*
- * Called when the tty is put into another line discipline
- * or it hangs up. We have to wait for any cpu currently
- * executing in any of the other ppp_synctty_* routines to
- * finish before we can call ppp_unregister_channel and free
- * the syncppp struct. This routine must be called from
- * process context, not interrupt or softirq context.
+ * Called when the tty is put into another line discipline or it hangs up.
+ * This call is serialized against other ldisc functions.
*/
static void
ppp_sync_close(struct tty_struct *tty)
{
- struct syncppp *ap;
+ struct syncppp *ap = tty->disc_data;
- write_lock_irq(&disc_data_lock);
- ap = tty->disc_data;
- tty->disc_data = NULL;
- write_unlock_irq(&disc_data_lock);
if (!ap)
return;
- /*
- * We have now ensured that nobody can start using ap from now
- * on, but we have to wait for all existing users to finish.
- * Note that ppp_unregister_channel ensures that no calls to
- * our channel ops (i.e. ppp_sync_send/ioctl) are in progress
- * by the time it returns.
- */
- if (!refcount_dec_and_test(&ap->refcnt))
- wait_for_completion(&ap->dead_cmp);
+ tty->disc_data = NULL;
tasklet_kill(&ap->tsk);
ppp_unregister_channel(&ap->chan);
@@ -238,17 +184,6 @@ ppp_sync_close(struct tty_struct *tty)
}
/*
- * Called on tty hangup in process context.
- *
- * Wait for I/O to driver to complete and unregister PPP channel.
- * This is already done by the close routine, so just call that.
- */
-static void ppp_sync_hangup(struct tty_struct *tty)
-{
- ppp_sync_close(tty);
-}
-
-/*
* Read does nothing - no data is ever available this way.
* Pppd reads and writes packets via /dev/ppp instead.
*/
@@ -273,7 +208,7 @@ ppp_sync_write(struct tty_struct *tty, struct file *file, const u8 *buf,
static int
ppp_synctty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
{
- struct syncppp *ap = sp_get(tty);
+ struct syncppp *ap = tty->disc_data;
int __user *p = (int __user *)arg;
int err, val;
@@ -314,7 +249,6 @@ ppp_synctty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
break;
}
- sp_put(ap);
return err;
}
@@ -323,7 +257,7 @@ static void
ppp_sync_receive(struct tty_struct *tty, const u8 *buf, const u8 *cflags,
size_t count)
{
- struct syncppp *ap = sp_get(tty);
+ struct syncppp *ap = tty->disc_data;
unsigned long flags;
if (!ap)
@@ -333,21 +267,19 @@ ppp_sync_receive(struct tty_struct *tty, const u8 *buf, const u8 *cflags,
spin_unlock_irqrestore(&ap->recv_lock, flags);
if (!skb_queue_empty(&ap->rqueue))
tasklet_schedule(&ap->tsk);
- sp_put(ap);
tty_unthrottle(tty);
}
static void
ppp_sync_wakeup(struct tty_struct *tty)
{
- struct syncppp *ap = sp_get(tty);
+ struct syncppp *ap = tty->disc_data;
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
if (!ap)
return;
set_bit(XMIT_WAKEUP, &ap->xmit_flags);
tasklet_schedule(&ap->tsk);
- sp_put(ap);
}
@@ -357,7 +289,6 @@ static struct tty_ldisc_ops ppp_sync_ldisc = {
.name = "pppsync",
.open = ppp_sync_open,
.close = ppp_sync_close,
- .hangup = ppp_sync_hangup,
.read = ppp_sync_read,
.write = ppp_sync_write,
.ioctl = ppp_synctty_ioctl,
@@ -524,17 +455,9 @@ ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *skb)
/* prepend address/control fields if necessary */
if ((ap->flags & SC_COMP_AC) == 0 || islcp) {
- if (skb_headroom(skb) < 2) {
- struct sk_buff *npkt = dev_alloc_skb(skb->len + 2);
- if (npkt == NULL) {
- kfree_skb(skb);
- return NULL;
- }
- skb_reserve(npkt,2);
- skb_copy_from_linear_data(skb,
- skb_put(npkt, skb->len), skb->len);
- consume_skb(skb);
- skb = npkt;
+ if (skb_cow_head(skb, 2)) {
+ kfree_skb(skb);
+ return NULL;
}
skb_push(skb,2);
skb->data[0] = PPP_ALLSTATIONS;
diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c
index 068acb052adb..5df657acf3d5 100644
--- a/drivers/net/usb/cx82310_eth.c
+++ b/drivers/net/usb/cx82310_eth.c
@@ -282,6 +282,7 @@ static int cx82310_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
if (len == 0xffff) {
netdev_info(dev->net, "router was rebooted, re-enabling ethernet mode");
schedule_work(&priv->reenable_work);
+ return 0;
} else if (len > CX82310_MTU) {
netdev_err(dev->net, "RX packet too long: %d B\n", len);
return 0;
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index c1aec67688ae..71caa3764b23 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -1547,10 +1547,10 @@ hso_wait_modem_status(struct hso_serial *serial, unsigned long arg)
spin_unlock_irq(&serial->serial_lock);
add_wait_queue(&tiocmget->waitq, &wait);
for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irq(&serial->serial_lock);
memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount));
spin_unlock_irq(&serial->serial_lock);
- set_current_state(TASK_INTERRUPTIBLE);
if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd))) {
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 8178a8758cd3..f51cf9cb9421 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1084,6 +1084,7 @@ static const struct usb_device_id products[] = {
},
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0122)}, /* Quectel RG650V */
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0125)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */
+ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x013d)}, /* Quectel RG660QB */
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0306)}, /* Quectel EP06/EG06/EM06 */
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)}, /* Quectel EM160R-GL */
@@ -1446,6 +1447,7 @@ static const struct usb_device_id products[] = {
{QMI_QUIRK_SET_DTR(0x2c7c, 0x0316, 3)}, /* Quectel RG255C */
{QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */
{QMI_QUIRK_SET_DTR(0x2cb7, 0x0112, 0)}, /* Fibocom FG132 */
+ {QMI_QUIRK_SET_DTR(0x04b7, 0x8217, 8)}, /* Compal EXM-G1x */
{QMI_FIXED_INTF(0x0489, 0xe0b4, 0)}, /* Foxconn T77W968 LTE */
{QMI_FIXED_INTF(0x0489, 0xe0b5, 0)}, /* Foxconn T77W968 LTE with eSIM support*/
{QMI_FIXED_INTF(0x2692, 0x9025, 4)}, /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 459f19f7071e..c1d54339fa2b 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -996,6 +996,12 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
return -EOPNOTSUPP;
}
+ if (rcu_access_pointer(f->nh) &&
+ !(state & (NUD_PERMANENT | NUD_NOARP))) {
+ NL_SET_ERR_MSG(extack, "Cannot make a nexthop fdb dynamic");
+ return -EOPNOTSUPP;
+ }
+
/* Do not allow an externally learned entry to take over an entry added
* by the user.
*/
@@ -1257,6 +1263,11 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
if (err)
return err;
+ if (nhid && !(ndm->ndm_state & (NUD_PERMANENT | NUD_NOARP))) {
+ NL_SET_ERR_MSG(extack, "A nexthop fdb cannot be dynamic");
+ return -EINVAL;
+ }
+
if (vxlan->default_dst.remote_ip.sa.sa_family != ip.sa.sa_family)
return -EAFNOSUPPORT;
@@ -2362,7 +2373,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
struct ip_tunnel_key key;
struct vxlan_dev *vxlan = netdev_priv(dev);
const struct iphdr *old_iph;
- struct vxlan_metadata _md;
+ struct vxlan_metadata _md = {};
struct vxlan_metadata *md = &_md;
unsigned int pkt_len = skb->len;
__be16 src_port = 0, dst_port;
diff --git a/drivers/net/vxlan/vxlan_mdb.c b/drivers/net/vxlan/vxlan_mdb.c
index d71e1925ecfd..841f42ffecb9 100644
--- a/drivers/net/vxlan/vxlan_mdb.c
+++ b/drivers/net/vxlan/vxlan_mdb.c
@@ -354,6 +354,10 @@ static bool vxlan_mdb_is_valid_source(const struct nlattr *attr, __be16 proto,
NL_SET_ERR_MSG_MOD(extack, "IPv4 multicast source address is not allowed");
return false;
}
+ if (ipv4_is_zeronet(nla_get_in_addr(attr))) {
+ NL_SET_ERR_MSG_MOD(extack, "IPv4 all-zeros source address is not allowed");
+ return false;
+ }
break;
#if IS_ENABLED(CONFIG_IPV6)
case htons(ETH_P_IPV6): {
@@ -368,6 +372,10 @@ static bool vxlan_mdb_is_valid_source(const struct nlattr *attr, __be16 proto,
NL_SET_ERR_MSG_MOD(extack, "IPv6 multicast source address is not allowed");
return false;
}
+ if (ipv6_addr_any(&src)) {
+ NL_SET_ERR_MSG_MOD(extack, "IPv6 all-zeros source address is not allowed");
+ return false;
+ }
break;
}
#endif
diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c
index 0fc55c9169e1..d89a49c6ebb7 100644
--- a/drivers/net/wireless/ath/ath12k/ahb.c
+++ b/drivers/net/wireless/ath/ath12k/ahb.c
@@ -870,7 +870,7 @@ static struct ath12k_ahb_rproc_info *ath12k_ahb_rproc_info_alloc(struct ath12k_b
lockdep_assert_held(&ath12k_rproc_info_lock);
- rproc_info = kzalloc_obj(*rproc_info, GFP_KERNEL);
+ rproc_info = kzalloc_obj(*rproc_info);
if (!rproc_info)
return NULL;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
index 533870cf443f..6db84c2117f2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
@@ -514,8 +514,7 @@ void iwl_mld_init_ap_type_tables(struct iwl_mld *mld)
return;
if (iwl_fw_lookup_cmd_ver(mld->fw, cmd.id, 1) == 1) {
- struct iwl_mcc_allowed_ap_type_cmd_v1 *cmd_v1 =
- kzalloc(sizeof(*cmd_v1), GFP_KERNEL);
+ struct iwl_mcc_allowed_ap_type_cmd_v1 *cmd_v1 = kzalloc_obj(*cmd_v1);
if (!cmd_v1)
return;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index a118a301564c..40546005c743 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -477,18 +477,23 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)
for (offset = 0; offset < len; offset += clc_len) {
if (len - offset < sizeof(*clc)) {
+ dev_err(mdev->dev, "Invalid CLC record\n");
ret = -EINVAL;
goto out;
}
clc = (const struct mt7921_clc *)(clc_base + offset);
clc_len = le32_to_cpu(clc->len);
- if (clc_len < sizeof(*clc) || clc_len > len - offset ||
- clc->idx >= ARRAY_SIZE(phy->clc)) {
+ if (clc_len < sizeof(*clc) || clc_len > len - offset) {
+ dev_err(mdev->dev, "Invalid CLC record\n");
ret = -EINVAL;
goto out;
}
+ /* Newer firmware may add records this driver does not use yet */
+ if (clc->idx >= ARRAY_SIZE(phy->clc))
+ continue;
+
/* do not init buf again if chip reset triggered */
if (phy->clc[clc->idx])
continue;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regd.c b/drivers/net/wireless/mediatek/mt76/mt7921/regd.c
index 4a8ea4624fee..fcdeb65cd8ef 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/regd.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/regd.c
@@ -289,7 +289,7 @@ int mt7921_regd_update(struct mt792x_phy *phy, char *alpha2)
goto err;
}
- regd = kzalloc(struct_size(regd, reg_rules, num_of_rules), GFP_KERNEL);
+ regd = kzalloc_flex(*regd, reg_rules, num_of_rules);
if (!regd) {
ret = -ENOMEM;
goto err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index 84b55f008b3d..5993b31e1aae 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -1105,7 +1105,7 @@ mt7925_mac_sta_add_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
mlink = &msta->deflink;
is_deflink = true;
} else {
- mlink = kzalloc(sizeof(*mlink), GFP_KERNEL);
+ mlink = kzalloc_obj(*mlink);
if (!mlink) {
err = -ENOMEM;
break;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regd.c b/drivers/net/wireless/mediatek/mt76/mt7925/regd.c
index f4beb7f52043..57f1736b54a3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/regd.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/regd.c
@@ -336,7 +336,7 @@ int mt7925_regd_update(struct mt792x_phy *phy, char *alpha2)
goto err;
}
- regd = kzalloc(struct_size(regd, reg_rules, num_of_rules), GFP_KERNEL);
+ regd = kzalloc_flex(*regd, reg_rules, num_of_rules);
if (!regd) {
ret = -ENOMEM;
goto err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c
index 946dd7956e4a..b468051fbe68 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c
@@ -323,7 +323,8 @@ int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default)
const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
int i;
- if (!phy->acpisar || !((struct mt792x_acpi_sar *)phy->acpisar)->dyn)
+ if (!capa || !phy->acpisar ||
+ !((struct mt792x_acpi_sar *)phy->acpisar)->dyn)
return 0;
/* When ACPI SAR enabled in HW, we should apply rules for .frp
diff --git a/drivers/net/wireless/morsemicro/mm81x/mac.c b/drivers/net/wireless/morsemicro/mm81x/mac.c
index 08ca116a68b4..0fa80b1488aa 100644
--- a/drivers/net/wireless/morsemicro/mm81x/mac.c
+++ b/drivers/net/wireless/morsemicro/mm81x/mac.c
@@ -706,8 +706,7 @@ static int mm81x_hw_scan_h_init_chan_list(struct mm81x_hw_scan_params *params,
params->num_chans = 0;
params->allocated_chans = 0;
- params->channels = kcalloc(chans_to_allocate, sizeof(*params->channels),
- GFP_KERNEL);
+ params->channels = kzalloc_objs(*params->channels, chans_to_allocate);
if (!params->channels)
return -ENOMEM;
@@ -728,8 +727,8 @@ static int mm81x_hw_scan_h_init_chan_list(struct mm81x_hw_scan_params *params,
}
}
- params->powers_qdbm = kmalloc_array(
- num_pwrs_coarse, sizeof(*params->powers_qdbm), GFP_KERNEL);
+ params->powers_qdbm = kmalloc_objs(*params->powers_qdbm,
+ num_pwrs_coarse);
if (!params->powers_qdbm)
return -ENOMEM;
@@ -822,7 +821,7 @@ __mm81x_hw_scan_h_init_params(struct mm81x *mors)
struct mm81x_hw_scan_params *params = mors->hw_scan.params;
if (!params) {
- params = kzalloc_obj(*params, GFP_KERNEL);
+ params = kzalloc_obj(*params);
if (params)
mors->hw_scan.params = params;
} else {
diff --git a/drivers/net/wireless/morsemicro/mm81x/yaps.c b/drivers/net/wireless/morsemicro/mm81x/yaps.c
index e98a2a58726f..2d1728c1a6de 100644
--- a/drivers/net/wireless/morsemicro/mm81x/yaps.c
+++ b/drivers/net/wireless/morsemicro/mm81x/yaps.c
@@ -22,15 +22,13 @@
static int mm81x_yaps_alloc_pkt_buffers(struct mm81x_yaps *yaps)
{
- yaps->hw.to_chip_pkts = kcalloc(MAX_PKTS_PER_TX_TXN,
- sizeof(*yaps->hw.to_chip_pkts),
- GFP_KERNEL);
+ yaps->hw.to_chip_pkts = kzalloc_objs(*yaps->hw.to_chip_pkts,
+ MAX_PKTS_PER_TX_TXN);
if (!yaps->hw.to_chip_pkts)
return -ENOMEM;
- yaps->hw.from_chip_pkts = kcalloc(MAX_PKTS_PER_RX_TXN,
- sizeof(*yaps->hw.from_chip_pkts),
- GFP_KERNEL);
+ yaps->hw.from_chip_pkts = kzalloc_objs(*yaps->hw.from_chip_pkts,
+ MAX_PKTS_PER_RX_TXN);
if (!yaps->hw.from_chip_pkts) {
kfree(yaps->hw.to_chip_pkts);
yaps->hw.to_chip_pkts = NULL;
diff --git a/drivers/net/wireless/nxp/nxpwifi/cfg80211.c b/drivers/net/wireless/nxp/nxpwifi/cfg80211.c
index 5cc8cdf594d3..86304ea3331c 100644
--- a/drivers/net/wireless/nxp/nxpwifi/cfg80211.c
+++ b/drivers/net/wireless/nxp/nxpwifi/cfg80211.c
@@ -641,7 +641,7 @@ nxpwifi_cfg80211_set_wiphy_params(struct wiphy *wiphy, int radio_idx, u32 change
switch (priv->bss_role) {
case NXPWIFI_BSS_ROLE_UAP:
- bss_cfg = kzalloc_obj(*bss_cfg, GFP_KERNEL);
+ bss_cfg = kzalloc_obj(*bss_cfg);
if (!bss_cfg) {
ret = -ENOMEM;
break;
@@ -1713,7 +1713,7 @@ static int nxpwifi_cfg80211_start_ap(struct wiphy *wiphy,
if (!nxpwifi_is_channel_setting_allowable(priv, params->chandef.chan))
return -EOPNOTSUPP;
- bss_cfg = kzalloc_obj(*bss_cfg, GFP_KERNEL);
+ bss_cfg = kzalloc_obj(*bss_cfg);
if (!bss_cfg)
return -ENOMEM;
@@ -1866,7 +1866,7 @@ nxpwifi_cfg80211_scan(struct wiphy *wiphy,
if (!nxpwifi_stop_bg_scan(priv))
cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0);
- user_scan_cfg = kzalloc_obj(*user_scan_cfg, GFP_KERNEL);
+ user_scan_cfg = kzalloc_obj(*user_scan_cfg);
if (!user_scan_cfg)
return -ENOMEM;
@@ -1973,7 +1973,7 @@ nxpwifi_cfg80211_sched_scan_start(struct wiphy *wiphy,
request->n_channels, request->scan_plans->interval,
(int)request->ie_len);
- bgscan_cfg = kzalloc_obj(*bgscan_cfg, GFP_KERNEL);
+ bgscan_cfg = kzalloc_obj(*bgscan_cfg);
if (!bgscan_cfg)
return -ENOMEM;
@@ -2304,7 +2304,7 @@ nxpwifi_setup_he_caps(struct nxpwifi_private *priv,
if (!hw_he_cap_len)
return;
- iftype_data = kmalloc_obj(*iftype_data, GFP_KERNEL);
+ iftype_data = kmalloc_obj(*iftype_data);
if (!iftype_data)
return;
memset(iftype_data, 0, sizeof(*iftype_data));
@@ -2759,7 +2759,7 @@ static int nxpwifi_set_mef_filter(struct nxpwifi_private *priv,
if (wowlan->n_patterns || wowlan->magic_pkt)
num_entries++;
- mef_entry = kzalloc_objs(*mef_entry, num_entries, GFP_KERNEL);
+ mef_entry = kzalloc_objs(*mef_entry, num_entries);
if (!mef_entry)
return -ENOMEM;
@@ -3227,7 +3227,7 @@ static int nxpwifi_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,
if (!tb[NXPWIFI_TM_ATTR_DATA])
return -EINVAL;
- hostcmd = kzalloc_obj(*hostcmd, GFP_KERNEL);
+ hostcmd = kzalloc_obj(*hostcmd);
if (!hostcmd)
return -ENOMEM;
diff --git a/drivers/net/wireless/nxp/nxpwifi/cmdevt.c b/drivers/net/wireless/nxp/nxpwifi/cmdevt.c
index 4eb17ada5db8..fc1950a125b6 100644
--- a/drivers/net/wireless/nxp/nxpwifi/cmdevt.c
+++ b/drivers/net/wireless/nxp/nxpwifi/cmdevt.c
@@ -302,7 +302,7 @@ int nxpwifi_alloc_cmd_buffer(struct nxpwifi_adapter *adapter)
/* Allocate and initialize struct cmd_ctrl_node */
cmd_array = kzalloc_objs(struct cmd_ctrl_node,
- NXPWIFI_NUM_OF_CMD_BUFFER, GFP_KERNEL);
+ NXPWIFI_NUM_OF_CMD_BUFFER);
if (!cmd_array)
return -ENOMEM;
diff --git a/drivers/net/wireless/nxp/nxpwifi/ie.c b/drivers/net/wireless/nxp/nxpwifi/ie.c
index 158755c0c905..86b18d50feaf 100644
--- a/drivers/net/wireless/nxp/nxpwifi/ie.c
+++ b/drivers/net/wireless/nxp/nxpwifi/ie.c
@@ -143,7 +143,7 @@ nxpwifi_update_uap_custom_ie(struct nxpwifi_private *priv,
u16 len;
int ret;
- ap_custom_ie = kzalloc_obj(*ap_custom_ie, GFP_KERNEL);
+ ap_custom_ie = kzalloc_obj(*ap_custom_ie);
if (!ap_custom_ie)
return -ENOMEM;
@@ -209,7 +209,7 @@ static int nxpwifi_update_vs_ie(const u8 *ies, int ies_len,
vendor_ie = cfg80211_find_vendor_ie(oui, oui_type, ies, ies_len);
if (vendor_ie) {
if (!*ie_ptr) {
- *ie_ptr = kzalloc_obj(struct nxpwifi_ie, GFP_KERNEL);
+ *ie_ptr = kzalloc_obj(struct nxpwifi_ie);
if (!*ie_ptr)
return -ENOMEM;
ie = *ie_ptr;
@@ -309,7 +309,7 @@ static int nxpwifi_uap_parse_tail_ies(struct nxpwifi_private *priv,
if (!info->tail || !info->tail_len)
return 0;
- gen_ie = kzalloc_obj(*gen_ie, GFP_KERNEL);
+ gen_ie = kzalloc_obj(*gen_ie);
if (!gen_ie)
return -ENOMEM;
@@ -417,7 +417,7 @@ int nxpwifi_del_mgmt_ies(struct nxpwifi_private *priv)
int ret = 0;
if (priv->gen_idx != NXPWIFI_AUTO_IDX_MASK) {
- gen_ie = kmalloc_obj(*gen_ie, GFP_KERNEL);
+ gen_ie = kmalloc_obj(*gen_ie);
if (!gen_ie)
return -ENOMEM;
@@ -434,7 +434,7 @@ int nxpwifi_del_mgmt_ies(struct nxpwifi_private *priv)
}
if (priv->beacon_idx != NXPWIFI_AUTO_IDX_MASK) {
- beacon_ie = kmalloc_obj(*beacon_ie, GFP_KERNEL);
+ beacon_ie = kmalloc_obj(*beacon_ie);
if (!beacon_ie) {
ret = -ENOMEM;
goto done;
@@ -444,7 +444,7 @@ int nxpwifi_del_mgmt_ies(struct nxpwifi_private *priv)
beacon_ie->ie_length = 0;
}
if (priv->proberesp_idx != NXPWIFI_AUTO_IDX_MASK) {
- pr_ie = kmalloc_obj(*pr_ie, GFP_KERNEL);
+ pr_ie = kmalloc_obj(*pr_ie);
if (!pr_ie) {
ret = -ENOMEM;
goto done;
@@ -454,7 +454,7 @@ int nxpwifi_del_mgmt_ies(struct nxpwifi_private *priv)
pr_ie->ie_length = 0;
}
if (priv->assocresp_idx != NXPWIFI_AUTO_IDX_MASK) {
- ar_ie = kmalloc_obj(*ar_ie, GFP_KERNEL);
+ ar_ie = kmalloc_obj(*ar_ie);
if (!ar_ie) {
ret = -ENOMEM;
goto done;
diff --git a/drivers/net/wireless/nxp/nxpwifi/init.c b/drivers/net/wireless/nxp/nxpwifi/init.c
index b128fc9fe31a..7c75dca5d0a8 100644
--- a/drivers/net/wireless/nxp/nxpwifi/init.c
+++ b/drivers/net/wireless/nxp/nxpwifi/init.c
@@ -20,7 +20,7 @@ static int nxpwifi_add_bss_prio_tbl(struct nxpwifi_private *priv)
struct nxpwifi_bss_prio_node *bss_prio;
struct nxpwifi_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
- bss_prio = kzalloc_obj(*bss_prio, GFP_KERNEL);
+ bss_prio = kzalloc_obj(*bss_prio);
if (!bss_prio)
return -ENOMEM;
diff --git a/drivers/net/wireless/nxp/nxpwifi/main.c b/drivers/net/wireless/nxp/nxpwifi/main.c
index b4c63829024a..55b962430f37 100644
--- a/drivers/net/wireless/nxp/nxpwifi/main.c
+++ b/drivers/net/wireless/nxp/nxpwifi/main.c
@@ -32,7 +32,7 @@ static struct nxpwifi_adapter *nxpwifi_register(void *card, struct device *dev,
int ret = 0;
int i;
- adapter = kzalloc_obj(*adapter, GFP_KERNEL);
+ adapter = kzalloc_obj(*adapter);
if (!adapter)
return ERR_PTR(-ENOMEM);
@@ -55,7 +55,7 @@ static struct nxpwifi_adapter *nxpwifi_register(void *card, struct device *dev,
for (i = 0; i < NXPWIFI_MAX_BSS_NUM; i++) {
/* Allocate memory for private structure */
adapter->priv[i] =
- kzalloc_obj(struct nxpwifi_private, GFP_KERNEL);
+ kzalloc_obj(struct nxpwifi_private);
if (!adapter->priv[i]) {
ret = -ENOMEM;
goto error;
@@ -1106,7 +1106,7 @@ void nxpwifi_drv_info_dump(struct nxpwifi_adapter *adapter)
p += adapter->if_ops.reg_dump(adapter, p);
}
p += sprintf(p, "\n=== more debug information\n");
- debug_info = kzalloc_obj(*debug_info, GFP_KERNEL);
+ debug_info = kzalloc_obj(*debug_info);
if (debug_info) {
for (i = 0; i < adapter->priv_num; i++) {
if (!adapter->priv[i]->netdev)
@@ -1242,7 +1242,7 @@ void nxpwifi_init_priv_params(struct nxpwifi_private *priv,
if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA ||
GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_UAP) {
- priv->hist_data = kmalloc_obj(*priv->hist_data, GFP_KERNEL);
+ priv->hist_data = kmalloc_obj(*priv->hist_data);
if (priv->hist_data)
nxpwifi_hist_data_reset(priv);
}
diff --git a/drivers/net/wireless/nxp/nxpwifi/scan.c b/drivers/net/wireless/nxp/nxpwifi/scan.c
index b77056983e83..67d7ff2f10c5 100644
--- a/drivers/net/wireless/nxp/nxpwifi/scan.c
+++ b/drivers/net/wireless/nxp/nxpwifi/scan.c
@@ -1341,15 +1341,14 @@ int nxpwifi_scan_networks(struct nxpwifi_private *priv,
adapter->scan_processing = true;
spin_unlock_bh(&adapter->nxpwifi_cmd_lock);
- scan_cfg_out = kzalloc_obj(union nxpwifi_scan_cmd_config_tlv,
- GFP_KERNEL);
+ scan_cfg_out = kzalloc_obj(union nxpwifi_scan_cmd_config_tlv);
if (!scan_cfg_out) {
ret = -ENOMEM;
goto done;
}
scan_chan_list = kzalloc_objs(struct nxpwifi_chan_scan_param_set,
- NXPWIFI_USER_SCAN_CHAN_MAX, GFP_KERNEL);
+ NXPWIFI_USER_SCAN_CHAN_MAX);
if (!scan_chan_list) {
kfree(scan_cfg_out);
ret = -ENOMEM;
@@ -1471,7 +1470,7 @@ static int nxpwifi_save_hidden_ssid_channels(struct nxpwifi_private *priv,
int chid;
/* Allocate and fill new bss descriptor */
- bss_desc = kzalloc_obj(*bss_desc, GFP_KERNEL);
+ bss_desc = kzalloc_obj(*bss_desc);
if (!bss_desc)
return -ENOMEM;
@@ -1512,7 +1511,7 @@ static int nxpwifi_update_curr_bss_params(struct nxpwifi_private *priv,
int ret;
/* Allocate and fill new bss descriptor */
- bss_desc = kzalloc_obj(*bss_desc, GFP_KERNEL);
+ bss_desc = kzalloc_obj(*bss_desc);
if (!bss_desc)
return -ENOMEM;
@@ -1751,7 +1750,7 @@ nxpwifi_active_scan_req_for_passive_chan(struct nxpwifi_private *priv)
nxpwifi_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
return 0;
}
- user_scan_cfg = kzalloc_obj(*user_scan_cfg, GFP_KERNEL);
+ user_scan_cfg = kzalloc_obj(*user_scan_cfg);
if (!user_scan_cfg)
return -ENOMEM;
@@ -2258,7 +2257,7 @@ int nxpwifi_stop_bg_scan(struct nxpwifi_private *priv)
return 0;
}
- bgscan_cfg = kzalloc_obj(*bgscan_cfg, GFP_KERNEL);
+ bgscan_cfg = kzalloc_obj(*bgscan_cfg);
if (!bgscan_cfg)
return -ENOMEM;
diff --git a/drivers/net/wireless/nxp/nxpwifi/sta_cfg.c b/drivers/net/wireless/nxp/nxpwifi/sta_cfg.c
index 702fa1531da1..56cf63fbf7fe 100644
--- a/drivers/net/wireless/nxp/nxpwifi/sta_cfg.c
+++ b/drivers/net/wireless/nxp/nxpwifi/sta_cfg.c
@@ -245,7 +245,7 @@ int nxpwifi_bss_start(struct nxpwifi_private *priv, struct cfg80211_bss *bss,
return -EINVAL;
/* Allocate and fill new bss descriptor */
- bss_desc = kzalloc_obj(*bss_desc, GFP_KERNEL);
+ bss_desc = kzalloc_obj(*bss_desc);
if (!bss_desc)
return -ENOMEM;
diff --git a/drivers/net/wireless/nxp/nxpwifi/sta_cmd.c b/drivers/net/wireless/nxp/nxpwifi/sta_cmd.c
index 5e8ffd306b31..9bfa4aebc3e5 100644
--- a/drivers/net/wireless/nxp/nxpwifi/sta_cmd.c
+++ b/drivers/net/wireless/nxp/nxpwifi/sta_cmd.c
@@ -2822,7 +2822,7 @@ nxpwifi_create_custom_regdomain(struct nxpwifi_private *priv,
if (WARN_ON_ONCE(num_chan > NL80211_MAX_SUPP_REG_RULES))
return ERR_PTR(-EINVAL);
- regd = kzalloc_flex(*regd, reg_rules, num_chan, GFP_KERNEL);
+ regd = kzalloc_flex(*regd, reg_rules, num_chan);
if (!regd)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/net/wireless/nxp/nxpwifi/uap_event.c b/drivers/net/wireless/nxp/nxpwifi/uap_event.c
index 9f717a3d7ec5..ab5c15686f54 100644
--- a/drivers/net/wireless/nxp/nxpwifi/uap_event.c
+++ b/drivers/net/wireless/nxp/nxpwifi/uap_event.c
@@ -88,7 +88,7 @@ nxpwifi_uap_event_sta_assoc(struct nxpwifi_private *priv)
struct nxpwifi_sta_node *node;
int len, i;
- sinfo = kzalloc_obj(*sinfo, GFP_KERNEL);
+ sinfo = kzalloc_obj(*sinfo);
if (!sinfo)
return -ENOMEM;