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

Pull networking fixes from Paolo Abeni:
 "Including fixes from netfilter, Bluetooth and batman-adv.

  Current release - regressions:

   - bluetooth: fix using chan->conn as indication to no remote netdev

  Current release - new code bugs:

   - netfilter: cap to maximum number of expectation per master on
     updates

  Previous releases - regressions:

   - bluetooth:
      - fix UAF of hci_conn_params in add_device_complete
      - fix null ptr deref in hci_abort_conn()

   - igmp: remove multicast group from hash table on device destruction

   - batman-adv: prevent TVLV OOB check overflow

   - eth: mlx5/mlx5e:
      - fix off-by-one in single-FDB error rollback
      - skip peer flow cleanup when LAG seq is unavailable
      - fix crashes in dynamic per-channel stats and HV VHCA agent

   - eth: mana: Sync page pool RX frags for CPU

  Previous releases - always broken:

   - netfilter:
      - mark malformed IPv6 extension headers for hotdrop
      - terminate table name before find_table_lock()
      - ipvs: use parsed transport offset in TCP state lookup

   - sched: act_pedit: fix TOCTOU heap OOB write in tc offload

   - ethtool: rss: fix hfunc and input_xfrm parsing on big endian

   - ipv4/ipv6: fix UAF and memory leak in IGMP/MLD

   - tls: consume empty data records in tls_sw_read_sock()

   - eth:
      - octeontx2-af: fix VF bringup affecting PF promiscuous state
      - gue: validate REMCSUM private option length"

* tag 'net-7.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (94 commits)
  macsec: don't read an unset MAC header in macsec_encrypt()
  dibs: loopback: validate offset and size in move_data()
  octeontx2-af: fix VF bringup affecting PF promiscuous state
  ethtool: rss: Fix hfunc and input_xfrm parsing on big endian
  net/mlx5: Fix L3 tunnel entropy refcount leak
  net: macb: drop in-flight Tx SKBs on close
  net: mana: Sync page pool RX frags for CPU
  net: mana: Validate the packet length reported by the NIC
  selftests/net: fix EVP_MD_CTX leak in tcp_mmap
  ipvs: ensure inner headers in ICMP errors are in headroom
  ipvs: use parsed transport offset in SCTP state lookup
  ipvs: use parsed transport offset in TCP state lookup
  ipvs: pass parsed transport offset to state handlers
  netfilter: handle unreadable frags
  netfilter: flowtable: support IPIP tunnel with direct xmit
  netfilter: flowtable: IPIP tunnel hardware offload is not yet support
  netfilter: flowtable: use dst in this direction when pushing IPIP header
  netfilter: ipset: allocate the proper memory for the generic hash structure
  netfilter: ipset: cleanup the add/del backlog when resize failed
  netfilter: ipset: exclude gc when resize is in progress
  ...
This commit is contained in:
Linus Torvalds
2026-07-09 08:26:51 -07:00
112 changed files with 1407 additions and 745 deletions
+6 -2
View File
@@ -255,9 +255,13 @@ static int bpa10x_setup(struct hci_dev *hdev)
if (IS_ERR(skb))
return PTR_ERR(skb);
bt_dev_info(hdev, "%s", (char *)(skb->data + 1));
/* Bounded print: the device controls skb->len. */
if (skb->len > 1) {
int len = skb->len - 1;
hci_set_fw_info(hdev, "%s", skb->data + 1);
bt_dev_info(hdev, "%.*s", len, (char *)(skb->data + 1));
hci_set_fw_info(hdev, "%.*s", len, skb->data + 1);
}
kfree_skb(skb);
return 0;
+52 -50
View File
@@ -2127,6 +2127,9 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
if (test_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags))
return -ENODEV;
if (test_bit(BTINTEL_PCIE_RECOVERY_IN_PROGRESS, &data->flags))
return -ENODEV;
/* Due to the fw limitation, the type header of the packet should be
* 4 bytes unlike 1 byte for UART. In UART, the firmware can read
* the first byte to get the packet type and redirect the rest of data
@@ -2485,7 +2488,6 @@ static void btintel_pcie_inc_recovery_count(struct pci_dev *pdev,
}
}
static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data);
static void btintel_pcie_reset(struct hci_dev *hdev);
static int btintel_pcie_acpi_reset_method(struct btintel_pcie_data *data)
@@ -2596,12 +2598,45 @@ static void btintel_pcie_perform_pldr(struct btintel_pcie_data *data)
}
}
/*
* Issue a Function Level Reset and hand teardown/re-init off to the PCI
* core via device_reprobe(), mirroring the PLDR path's contract.
*
* Caller must hold pci_lock_rescan_remove() and must have already
* disabled interrupts and drained both rx_work and coredump_work.
*/
static int btintel_pcie_perform_flr(struct btintel_pcie_data *data)
{
struct pci_dev *pdev = data->pdev;
int err;
/* pci_try_reset_function() avoids the device_lock ABBA against
* btintel_pcie_remove(): .remove() runs with device_lock held and
* then waits for this work via disable_work_sync(); the blocking
* pci_reset_function() would deadlock by trying to re-acquire
* device_lock here.
*/
err = pci_try_reset_function(pdev);
if (err) {
BT_ERR("Failed resetting the pcie device (%d)", err);
return err;
}
/* device_reprobe() always detaches the driver first (running
* .remove(), which frees 'data'); any re-probe failure leaves the
* device unbound but 'data' is already gone, so just log it.
*/
if (device_reprobe(&pdev->dev))
BT_ERR("BT reprobe failed for BDF:%s", pci_name(pdev));
return 0;
}
static void btintel_pcie_reset_work(struct work_struct *wk)
{
struct btintel_pcie_data *data =
container_of(wk, struct btintel_pcie_data, reset_work);
struct pci_dev *pdev = data->pdev;
int err;
pci_lock_rescan_remove();
@@ -2621,60 +2656,27 @@ static void btintel_pcie_reset_work(struct work_struct *wk)
disable_work_sync(&data->coredump_work);
bt_dev_dbg(data->hdev, "Release bluetooth interface");
/* Both reset paths follow the same contract: on success they
* destroy 'data' via device_reprobe() (a fresh probe re-INIT_WORKs
* the coredump_work with disable count 0), so enable_work() must
* NOT be called on the success path. Only the FLR path can fail
* with 'data' still alive, in which case we balance the
* disable_work_sync() above so a later successful reset is not
* permanently blocked.
*
* pci_lock_rescan_remove() (held above) serializes against PCI
* device addition/removal (hotplug), so no device can be added to
* or removed from the bus list while this code runs.
*/
if (data->reset_type == BTINTEL_PCIE_IOSF_PRR_PLDR) {
/* This function holds pci_lock_rescan_remove(), which acquires
* pci_rescan_remove_lock. This mutex serializes against PCI device
* addition/removal (hotplug), so no device can be added to or
* removed from the bus list while this code runs.
*
* device_reprobe() inside btintel_pcie_perform_pldr() destroys
* 'data' via .remove(); a fresh probe re-INIT_WORKs the
* coredump_work with disable count 0, so we must not call
* enable_work() on this path.
*/
btintel_pcie_perform_pldr(data);
goto out;
}
btintel_pcie_release_hdev(data);
/* Use pci_try_reset_function() rather than pci_reset_function() to
* avoid an ABBA deadlock against btintel_pcie_remove(): the PCI core
* calls .remove() with device_lock held, and remove() then waits for
* this work via cancel_work_sync(); pci_reset_function() would in
* turn try to acquire the same device_lock, deadlocking both paths.
*/
err = pci_try_reset_function(pdev);
if (err) {
BT_ERR("Failed resetting the pcie device (%d)", err);
goto out_enable;
}
if (btintel_pcie_perform_flr(data))
enable_work(&data->coredump_work);
btintel_pcie_enable_interrupts(data);
btintel_pcie_config_msix(data);
err = btintel_pcie_enable_bt(data);
if (err) {
BT_ERR("Failed to enable bluetooth hardware after reset (%d)",
err);
goto out_enable;
}
btintel_pcie_reset_ia(data);
btintel_pcie_start_rx(data);
data->flags = 0;
err = btintel_pcie_setup_hdev(data);
if (err) {
BT_ERR("Failed registering hdev (%d)", err);
goto out_enable;
}
out_enable:
/* Balance disable_work_sync() above on every exit. Leaving the
* counter incremented on a failed reset would permanently disable
* coredump_work even after a later successful reset.
*/
enable_work(&data->coredump_work);
out:
pci_dev_put(pdev);
pci_unlock_rescan_remove();
+6
View File
@@ -1267,6 +1267,12 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
}
nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;
if (nxpdev->fw_dnld_v3_offset >= nxpdev->fw->size ||
len > nxpdev->fw->size - nxpdev->fw_dnld_v3_offset) {
bt_dev_err(hdev, "FW download out of bounds, ignoring request");
len = 0;
goto free_skb;
}
serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
nxpdev->fw_dnld_v3_offset, len);
+10 -4
View File
@@ -239,6 +239,8 @@ static int hci_uart_flush(struct hci_dev *hdev)
BT_DBG("hdev %p tty %p", hdev, tty);
disable_work_sync(&hu->write_work);
if (hu->tx_skb) {
kfree_skb(hu->tx_skb); hu->tx_skb = NULL;
}
@@ -254,6 +256,14 @@ static int hci_uart_flush(struct hci_dev *hdev)
percpu_up_read(&hu->proto_lock);
/* Resume TX. Also reschedule in case work was queued concurrently;
* this may schedule write_work although there's nothing to do.
*/
enable_work(&hu->write_work);
clear_bit(HCI_UART_SENDING, &hu->tx_state);
if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state))
hci_uart_tx_wakeup(hu);
return 0;
}
@@ -271,12 +281,8 @@ static int hci_uart_open(struct hci_dev *hdev)
/* Close device */
static int hci_uart_close(struct hci_dev *hdev)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
BT_DBG("hdev %p", hdev);
cancel_work_sync(&hu->write_work);
hci_uart_flush(hdev);
hdev->flush = NULL;
return 0;
+5
View File
@@ -254,6 +254,11 @@ static int dibs_lo_move_data(struct dibs_dev *dibs, u64 dmb_tok,
read_unlock_bh(&ldev->dmb_ht_lock);
return -EINVAL;
}
if ((u64)offset + size > rmb_node->len) {
read_unlock_bh(&ldev->dmb_ht_lock);
return -EINVAL;
}
memcpy((char *)rmb_node->cpu_addr + offset, data, size);
sba_idx = rmb_node->sba_idx;
read_unlock_bh(&ldev->dmb_ht_lock);
+3 -3
View File
@@ -3301,9 +3301,9 @@ static size_t amt_get_size(const struct net_device *dev)
nla_total_size(sizeof(__u16)) + /* IFLA_AMT_GATEWAY_PORT */
nla_total_size(sizeof(__u32)) + /* IFLA_AMT_LINK */
nla_total_size(sizeof(__u32)) + /* IFLA_MAX_TUNNELS */
nla_total_size(sizeof(struct iphdr)) + /* IFLA_AMT_DISCOVERY_IP */
nla_total_size(sizeof(struct iphdr)) + /* IFLA_AMT_REMOTE_IP */
nla_total_size(sizeof(struct iphdr)); /* IFLA_AMT_LOCAL_IP */
nla_total_size(sizeof(__be32)) + /* IFLA_AMT_DISCOVERY_IP */
nla_total_size(sizeof(__be32)) + /* IFLA_AMT_REMOTE_IP */
nla_total_size(sizeof(__be32)); /* IFLA_AMT_LOCAL_IP */
}
static int amt_fill_info(struct sk_buff *skb, const struct net_device *dev)
+19 -2
View File
@@ -2668,8 +2668,25 @@ static void macb_free_consistent(struct macb *bp)
dma_free_coherent(dev, size, bp->queues[0].rx_ring, bp->queues[0].rx_ring_dma);
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
kfree(queue->tx_skb);
queue->tx_skb = NULL;
if (queue->tx_skb) {
unsigned int dropped = 0, tail;
for (tail = queue->tx_tail; tail != queue->tx_head;
tail++) {
if (macb_tx_skb(queue, tail)->skb)
dropped++;
macb_tx_unmap(bp, macb_tx_skb(queue, tail), 0);
}
queue->stats.tx_dropped += dropped;
bp->dev->stats.tx_dropped += dropped;
kfree(queue->tx_skb);
queue->tx_skb = NULL;
}
queue->tx_head = 0;
queue->tx_tail = 0;
queue->tx_ring = NULL;
queue->rx_ring = NULL;
}
@@ -3779,9 +3779,7 @@ setup_nic_dev_done:
static int octeon_enable_sriov(struct octeon_device *oct)
{
unsigned int num_vfs_alloced = oct->sriov_info.num_vfs_alloced;
struct pci_dev *vfdev;
int err;
u32 u;
if (OCTEON_CN23XX_PF(oct) && num_vfs_alloced) {
err = pci_enable_sriov(oct->pci_dev,
@@ -3794,23 +3792,6 @@ static int octeon_enable_sriov(struct octeon_device *oct)
return err;
}
oct->sriov_info.sriov_enabled = 1;
/* init lookup table that maps DPI ring number to VF pci_dev
* struct pointer
*/
u = 0;
vfdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
OCTEON_CN23XX_VF_VID, NULL);
while (vfdev) {
if (vfdev->is_virtfn &&
(vfdev->physfn == oct->pci_dev)) {
oct->sriov_info.dpiring_to_vfpcidev_lut[u] =
vfdev;
u += oct->sriov_info.rings_per_vf;
}
vfdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
OCTEON_CN23XX_VF_VID, vfdev);
}
}
return num_vfs_alloced;
@@ -3818,8 +3799,6 @@ static int octeon_enable_sriov(struct octeon_device *oct)
static int lio_pci_sriov_disable(struct octeon_device *oct)
{
int u;
if (pci_vfs_assigned(oct->pci_dev)) {
dev_err(&oct->pci_dev->dev, "VFs are still assigned to VMs.\n");
return -EPERM;
@@ -3827,12 +3806,6 @@ static int lio_pci_sriov_disable(struct octeon_device *oct)
pci_disable_sriov(oct->pci_dev);
u = 0;
while (u < MAX_POSSIBLE_VFS) {
oct->sriov_info.dpiring_to_vfpcidev_lut[u] = NULL;
u += oct->sriov_info.rings_per_vf;
}
oct->sriov_info.num_vfs_alloced = 0;
dev_info(&oct->pci_dev->dev, "oct->pf_num:%d disabled VFs\n",
oct->pf_num);
@@ -390,9 +390,6 @@ struct octeon_sriov_info {
struct lio_trusted_vf trusted_vf;
/*lookup table that maps DPI ring number to VF pci_dev struct pointer*/
struct pci_dev *dpiring_to_vfpcidev_lut[MAX_POSSIBLE_VFS];
u64 vf_macaddr[MAX_POSSIBLE_VFS];
u16 vf_vlantci[MAX_POSSIBLE_VFS];
@@ -26,6 +26,31 @@
#include "octeon_mailbox.h"
#include "cn23xx_pf_device.h"
static struct pci_dev *lio_vf_pci_dev_by_qno(struct octeon_device *oct, u32 q_no)
{
struct pci_dev *vfdev = NULL;
int vfidx;
if (!oct->sriov_info.rings_per_vf)
return NULL;
if (q_no % oct->sriov_info.rings_per_vf)
return NULL;
vfidx = q_no / oct->sriov_info.rings_per_vf;
if (vfidx >= oct->sriov_info.num_vfs_alloced)
return NULL;
while ((vfdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
OCTEON_CN23XX_VF_VID, vfdev))) {
if (pci_physfn(vfdev) && pci_physfn(vfdev) == oct->pci_dev &&
pci_iov_vf_id(vfdev) == vfidx)
return vfdev;
}
return NULL;
}
/**
* octeon_mbox_read:
* @mbox: Pointer mailbox
@@ -237,6 +262,7 @@ static int octeon_mbox_process_cmd(struct octeon_mbox *mbox,
struct octeon_mbox_cmd *mbox_cmd)
{
struct octeon_device *oct = mbox->oct_dev;
struct pci_dev *vfdev;
switch (mbox_cmd->msg.s.cmd) {
case OCTEON_VF_ACTIVE:
@@ -260,7 +286,12 @@ static int octeon_mbox_process_cmd(struct octeon_mbox *mbox,
dev_info(&oct->pci_dev->dev,
"got a request for FLR from VF that owns DPI ring %u\n",
mbox->q_no);
pcie_flr(oct->sriov_info.dpiring_to_vfpcidev_lut[mbox->q_no]);
vfdev = lio_vf_pci_dev_by_qno(oct, mbox->q_no);
if (!vfdev)
break;
pcie_flr(vfdev);
pci_dev_put(vfdev);
break;
case OCTEON_PF_CHANGED_VF_MACADDR:
@@ -4580,7 +4580,7 @@ int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req,
rvu_npc_install_allmulti_entry(rvu, pcifunc, nixlf,
pfvf->rx_chan_base);
} else {
if (!nix_rx_multicast)
if (!nix_rx_multicast && !is_vf(pcifunc))
rvu_npc_enable_allmulti_entry(rvu, pcifunc, nixlf, false);
}
@@ -4590,7 +4590,7 @@ int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req,
pfvf->rx_chan_base,
pfvf->rx_chan_cnt);
else
if (!nix_rx_multicast)
if (!nix_rx_multicast && !is_vf(pcifunc))
rvu_npc_enable_promisc_entry(rvu, pcifunc, nixlf, false);
return 0;
@@ -1568,15 +1568,15 @@ static void otx2_free_sq_res(struct otx2_nic *pf)
otx2_sq_free_sqbs(pf);
for (qidx = 0; qidx < otx2_get_total_tx_queues(pf); qidx++) {
sq = &qset->sq[qidx];
/* Skip freeing Qos queues if they are not initialized */
if (!sq->sqe)
continue;
qmem_free(pf->dev, sq->sqe);
qmem_free(pf->dev, sq->sqe_ring);
qmem_free(pf->dev, sq->cpt_resp);
qmem_free(pf->dev, sq->tso_hdrs);
qmem_free(pf->dev, sq->timestamps);
kfree(sq->sg);
/* sq->sqe is not initialized for unused QoS queues */
if (sq->sqe) {
qmem_free(pf->dev, sq->sqe);
qmem_free(pf->dev, sq->sqe_ring);
qmem_free(pf->dev, sq->cpt_resp);
qmem_free(pf->dev, sq->tso_hdrs);
qmem_free(pf->dev, sq->timestamps);
kfree(sq->sg);
}
kfree(sq->sqb_ptrs);
}
}
@@ -1711,13 +1711,12 @@ int otx2_init_hw_resources(struct otx2_nic *pf)
return err;
err_free_nix_queues:
otx2_free_sq_res(pf);
otx2_free_cq_res(pf);
otx2_ctx_disable(mbox, NIX_AQ_CTYPE_RQ, false);
err_free_txsch:
otx2_txschq_stop(pf);
err_free_sq_ptrs:
otx2_sq_free_sqbs(pf);
otx2_free_sq_res(pf);
err_free_rq_ptrs:
otx2_free_aura_ptr(pf, AURA_NIX_RQ);
otx2_ctx_disable(mbox, NPA_AQ_CTYPE_POOL, true);
@@ -2517,10 +2516,42 @@ EXPORT_SYMBOL(otx2_config_hwtstamp_set);
static int otx2_do_set_vf_mac(struct otx2_nic *pf, int vf, const u8 *mac)
{
struct npc_get_field_status_req *freq;
struct npc_get_field_status_rsp *frsp;
struct npc_install_flow_req *req;
int err;
mutex_lock(&pf->mbox.lock);
/* Skip installing the DMAC filter if the hardware parser profile
* does not support DMAC extraction.
*/
freq = otx2_mbox_alloc_msg_npc_get_field_status(&pf->mbox);
if (!freq) {
err = -ENOMEM;
goto out;
}
freq->field = NPC_DMAC;
err = otx2_sync_mbox_msg(&pf->mbox);
if (err)
goto out;
frsp = (struct npc_get_field_status_rsp *)otx2_mbox_get_rsp
(&pf->mbox.mbox, 0, &freq->hdr);
if (IS_ERR(frsp)) {
err = PTR_ERR(frsp);
goto out;
}
if (!frsp->enable) {
netdev_warn(pf->netdev,
"VF %d MAC filter not installed: DMAC extraction not supported by parser profile\n",
vf);
err = -EOPNOTSUPP;
goto out;
}
req = otx2_mbox_alloc_msg_npc_install_flow(&pf->mbox);
if (!req) {
err = -ENOMEM;
@@ -2559,13 +2590,12 @@ static int otx2_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
if (!is_valid_ether_addr(mac))
return -EINVAL;
config = &pf->vf_configs[vf];
ether_addr_copy(config->mac, mac);
ret = otx2_do_set_vf_mac(pf, vf, mac);
if (ret == 0)
dev_info(&pdev->dev,
"Load/Reload VF driver\n");
if (ret == 0) {
config = &pf->vf_configs[vf];
ether_addr_copy(config->mac, mac);
dev_info(&pdev->dev, "Load/Reload VF driver\n");
}
return ret;
}
@@ -987,6 +987,18 @@ struct mlx5e_priv {
struct ethtool_fec_hist_range *fec_ranges;
};
static inline u16 mlx5e_stats_nch_read(const struct mlx5e_priv *priv)
{
/* Pairs with smp_store_release in mlx5e_stats_nch_write(). */
return smp_load_acquire(&priv->stats_nch);
}
static inline void mlx5e_stats_nch_write(struct mlx5e_priv *priv, u16 n)
{
/* Pairs with smp_load_acquire in mlx5e_stats_nch_read(). */
smp_store_release(&priv->stats_nch, n);
}
struct mlx5e_dev {
struct net_device *netdev;
struct devlink_port dl_port;
@@ -33,9 +33,10 @@ mlx5e_hv_vhca_fill_ring_stats(struct mlx5e_priv *priv, int ch,
static void mlx5e_hv_vhca_fill_stats(struct mlx5e_priv *priv, void *data,
int buf_len)
{
u16 nch = mlx5e_stats_nch_read(priv);
int ch, i = 0;
for (ch = 0; ch < priv->stats_nch; ch++) {
for (ch = 0; ch < nch; ch++) {
void *buf = data + i;
if (WARN_ON_ONCE(buf +
@@ -49,9 +50,16 @@ static void mlx5e_hv_vhca_fill_stats(struct mlx5e_priv *priv, void *data,
}
static int mlx5e_hv_vhca_stats_buf_size(struct mlx5e_priv *priv)
{
u16 nch = mlx5e_stats_nch_read(priv);
return sizeof(struct mlx5e_hv_vhca_per_ring_stats) * nch;
}
static int mlx5e_hv_vhca_stats_buf_max_size(struct mlx5e_priv *priv)
{
return (sizeof(struct mlx5e_hv_vhca_per_ring_stats) *
priv->stats_nch);
max(priv->max_nch, priv->stats_nch));
}
static void mlx5e_hv_vhca_stats_work(struct work_struct *work)
@@ -67,7 +75,7 @@ static void mlx5e_hv_vhca_stats_work(struct work_struct *work)
sagent = container_of(dwork, struct mlx5e_hv_vhca_stats_agent, work);
priv = container_of(sagent, struct mlx5e_priv, stats_agent);
buf_len = mlx5e_hv_vhca_stats_buf_size(priv);
agent = sagent->agent;
agent = READ_ONCE(sagent->agent);
buf = sagent->buf;
memset(buf, 0, buf_len);
@@ -100,7 +108,7 @@ static void mlx5e_hv_vhca_stats_control(struct mlx5_hv_vhca_agent *agent,
sagent = &priv->stats_agent;
block->version = MLX5_HV_VHCA_STATS_VERSION;
block->rings = priv->stats_nch;
block->rings = mlx5e_stats_nch_read(priv);
if (!block->command) {
cancel_delayed_work_sync(&priv->stats_agent.work);
@@ -122,18 +130,21 @@ static void mlx5e_hv_vhca_stats_cleanup(struct mlx5_hv_vhca_agent *agent)
void mlx5e_hv_vhca_stats_create(struct mlx5e_priv *priv)
{
int buf_len = mlx5e_hv_vhca_stats_buf_size(priv);
int buf_len = mlx5e_hv_vhca_stats_buf_max_size(priv);
struct mlx5_hv_vhca_agent *agent;
priv->stats_agent.buf = kvzalloc(buf_len, GFP_KERNEL);
if (!priv->stats_agent.buf)
return;
INIT_DELAYED_WORK(&priv->stats_agent.work, mlx5e_hv_vhca_stats_work);
agent = mlx5_hv_vhca_agent_create(priv->mdev->hv_vhca,
MLX5_HV_VHCA_AGENT_STATS,
mlx5e_hv_vhca_stats_control, NULL,
mlx5e_hv_vhca_stats_cleanup,
priv);
priv,
&priv->stats_agent.agent);
if (IS_ERR_OR_NULL(agent)) {
if (IS_ERR(agent))
@@ -142,18 +153,20 @@ void mlx5e_hv_vhca_stats_create(struct mlx5e_priv *priv)
agent);
kvfree(priv->stats_agent.buf);
return;
priv->stats_agent.buf = NULL;
}
priv->stats_agent.agent = agent;
INIT_DELAYED_WORK(&priv->stats_agent.work, mlx5e_hv_vhca_stats_work);
}
void mlx5e_hv_vhca_stats_destroy(struct mlx5e_priv *priv)
{
if (IS_ERR_OR_NULL(priv->stats_agent.agent))
struct mlx5_hv_vhca_agent *agent;
agent = READ_ONCE(priv->stats_agent.agent);
if (IS_ERR_OR_NULL(agent))
return;
mlx5_hv_vhca_agent_destroy(priv->stats_agent.agent);
mlx5_hv_vhca_agent_destroy(agent);
WRITE_ONCE(priv->stats_agent.agent, NULL);
kvfree(priv->stats_agent.buf);
priv->stats_agent.buf = NULL;
}
@@ -2773,7 +2773,7 @@ static int mlx5e_channel_stats_alloc(struct mlx5e_priv *priv, int ix, int cpu)
GFP_KERNEL, cpu_to_node(cpu));
if (!priv->channel_stats[ix])
return -ENOMEM;
priv->stats_nch++;
mlx5e_stats_nch_write(priv, priv->stats_nch + 1);
return 0;
}
@@ -4040,9 +4040,10 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s)
{
u16 nch = mlx5e_stats_nch_read(priv);
int i;
for (i = 0; i < priv->stats_nch; i++) {
for (i = 0; i < nch; i++) {
struct mlx5e_channel_stats *channel_stats = priv->channel_stats[i];
struct mlx5e_rq_stats *xskrq_stats = &channel_stats->xskrq;
struct mlx5e_rq_stats *rq_stats = &channel_stats->rq;
@@ -5488,7 +5489,7 @@ static void mlx5e_get_queue_stats_rx(struct net_device *dev, int i,
struct mlx5e_rq_stats *xskrq_stats;
struct mlx5e_rq_stats *rq_stats;
if (mlx5e_is_uplink_rep(priv) || !priv->stats_nch)
if (mlx5e_is_uplink_rep(priv) || !mlx5e_stats_nch_read(priv))
return;
channel_stats = priv->channel_stats[i];
@@ -5512,7 +5513,7 @@ static void mlx5e_get_queue_stats_tx(struct net_device *dev, int i,
struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5e_sq_stats *sq_stats;
if (!priv->stats_nch)
if (!mlx5e_stats_nch_read(priv))
return;
/* no special case needed for ptp htb etc since txq2sq_stats is kept up
@@ -5538,6 +5539,7 @@ static void mlx5e_get_base_stats(struct net_device *dev,
struct netdev_queue_stats_tx *tx)
{
struct mlx5e_priv *priv = netdev_priv(dev);
u16 nch = mlx5e_stats_nch_read(priv);
struct mlx5e_ptp *ptp_channel;
int i, tc;
@@ -5549,7 +5551,7 @@ static void mlx5e_get_base_stats(struct net_device *dev,
rx->hw_gro_wire_packets = 0;
rx->hw_gro_wire_bytes = 0;
for (i = priv->channels.params.num_channels; i < priv->stats_nch; i++) {
for (i = priv->channels.params.num_channels; i < nch; i++) {
struct netdev_queue_stats_rx rx_i = {0};
mlx5e_get_queue_stats_rx(dev, i, &rx_i);
@@ -5585,7 +5587,7 @@ static void mlx5e_get_base_stats(struct net_device *dev,
tx->stop = 0;
tx->wake = 0;
for (i = 0; i < priv->stats_nch; i++) {
for (i = 0; i < nch; i++) {
struct mlx5e_channel_stats *channel_stats = priv->channel_stats[i];
/* handle two cases:
@@ -515,6 +515,7 @@ static void mlx5e_stats_update_stats_rq_page_pool(struct mlx5e_channel *c)
static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(sw)
{
struct mlx5e_sw_stats *s = &priv->stats.sw;
u16 nch = mlx5e_stats_nch_read(priv);
int i;
memset(s, 0, sizeof(*s));
@@ -522,7 +523,7 @@ static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(sw)
for (i = 0; i < priv->channels.num; i++) /* for active channels only */
mlx5e_stats_update_stats_rq_page_pool(priv->channels.c[i]);
for (i = 0; i < priv->stats_nch; i++) {
for (i = 0; i < nch; i++) {
struct mlx5e_channel_stats *channel_stats =
priv->channel_stats[i];
@@ -2614,7 +2615,7 @@ static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(ptp) { return; }
static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(channels)
{
int max_nch = priv->stats_nch;
int max_nch = mlx5e_stats_nch_read(priv);
return (NUM_RQ_STATS * max_nch) +
(NUM_CH_STATS * max_nch) +
@@ -2627,8 +2628,8 @@ static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(channels)
static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(channels)
{
int max_nch = mlx5e_stats_nch_read(priv);
bool is_xsk = priv->xsk.ever_used;
int max_nch = priv->stats_nch;
int i, j, tc;
for (i = 0; i < max_nch; i++)
@@ -2660,8 +2661,8 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(channels)
static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(channels)
{
int max_nch = mlx5e_stats_nch_read(priv);
bool is_xsk = priv->xsk.ever_used;
int max_nch = priv->stats_nch;
int i, j, tc;
for (i = 0; i < max_nch; i++)
@@ -5547,6 +5547,9 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw)
mlx5_devcom_for_each_peer_entry(devcom, peer_esw, pos) {
i = mlx5_lag_get_dev_seq(peer_esw->dev);
if (i < 0)
continue;
list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows[i], peer[i])
mlx5e_tc_del_fdb_peers_flow(flow);
}
@@ -135,10 +135,11 @@ void mlx5i_cleanup(struct mlx5e_priv *priv)
static void mlx5i_grp_sw_update_stats(struct mlx5e_priv *priv)
{
u16 nch = mlx5e_stats_nch_read(priv);
struct rtnl_link_stats64 s = {};
int i, j;
for (i = 0; i < priv->stats_nch; i++) {
for (i = 0; i < nch; i++) {
struct mlx5e_channel_stats *channel_stats;
struct mlx5e_rq_stats *rq_stats;
@@ -194,8 +194,10 @@ static void mlx5_mpesw_work(struct work_struct *work)
struct mlx5_lag *ldev = mpesww->lag;
devcom = mlx5_lag_get_devcom_comp(ldev);
if (!devcom)
return;
if (!devcom) {
mpesww->result = -ENODEV;
goto complete;
}
mlx5_devcom_comp_lock(devcom);
mlx5_mpesw_sd_devcoms_lock(ldev);
@@ -213,6 +215,7 @@ unlock:
mutex_unlock(&ldev->lock);
mlx5_mpesw_sd_devcoms_unlock(ldev);
mlx5_devcom_comp_unlock(devcom);
complete:
complete(&mpesww->comp);
}
@@ -78,7 +78,7 @@ static int mlx5_lag_create_single_fdb_filter(struct mlx5_lag *ldev, u32 filter)
}
return 0;
err:
mlx5_lag_for_each_reverse(j, i, 0, ldev, filter) {
mlx5_lag_for_each_reverse(j, i - 1, 0, ldev, filter) {
struct mlx5_eswitch *slave_esw;
if (j == master_idx)

Some files were not shown because too many files have changed in this diff Show More