mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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:
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user