]> www.infradead.org Git - users/hch/misc.git/commitdiff
bnxt_en: Add TPH support in BNXT driver
authorManoj Panicker <manoj.panicker2@amd.com>
Thu, 13 Feb 2025 01:12:39 +0000 (17:12 -0800)
committerJakub Kicinski <kuba@kernel.org>
Sat, 15 Feb 2025 03:50:23 +0000 (19:50 -0800)
Add TPH support to the Broadcom BNXT device driver. This allows the
driver to utilize TPH functions for retrieving and configuring Steering
Tags when changing interrupt affinity. With compatible NIC firmware,
network traffic will be tagged correctly with Steering Tags, resulting
in significant memory bandwidth savings and other advantages as
demonstrated by real network benchmarks on TPH-capable platforms.

Co-developed-by: Somnath Kotur <somnath.kotur@broadcom.com>
Signed-off-by: Somnath Kotur <somnath.kotur@broadcom.com>
Co-developed-by: Wei Huang <wei.huang2@amd.com>
Signed-off-by: Wei Huang <wei.huang2@amd.com>
Signed-off-by: Manoj Panicker <manoj.panicker2@amd.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Link: https://patch.msgid.link/20250213011240.1640031-12-michael.chan@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h

index 1997cdbd58018ef46f51f9c92053c62cdfac0856..15c57a06ecaf41e89ce3fa61a9ff02a81610ecaf 100644 (file)
@@ -55,6 +55,8 @@
 #include <net/page_pool/helpers.h>
 #include <linux/align.h>
 #include <net/netdev_queues.h>
+#include <net/netdev_rx_queue.h>
+#include <linux/pci-tph.h>
 
 #include "bnxt_hsi.h"
 #include "bnxt.h"
@@ -76,6 +78,7 @@
 #define BNXT_DEF_MSG_ENABLE    (NETIF_MSG_DRV | NETIF_MSG_HW | \
                                 NETIF_MSG_TX_ERR)
 
+MODULE_IMPORT_NS("NETDEV_INTERNAL");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Broadcom NetXtreme network driver");
 
@@ -11351,6 +11354,83 @@ start_tx:
        return 0;
 }
 
+static void bnxt_irq_affinity_notify(struct irq_affinity_notify *notify,
+                                    const cpumask_t *mask)
+{
+       struct bnxt_irq *irq;
+       u16 tag;
+       int err;
+
+       irq = container_of(notify, struct bnxt_irq, affinity_notify);
+
+       if (!irq->bp->tph_mode)
+               return;
+
+       cpumask_copy(irq->cpu_mask, mask);
+
+       if (irq->ring_nr >= irq->bp->rx_nr_rings)
+               return;
+
+       if (pcie_tph_get_cpu_st(irq->bp->pdev, TPH_MEM_TYPE_VM,
+                               cpumask_first(irq->cpu_mask), &tag))
+               return;
+
+       if (pcie_tph_set_st_entry(irq->bp->pdev, irq->msix_nr, tag))
+               return;
+
+       rtnl_lock();
+       if (netif_running(irq->bp->dev)) {
+               err = netdev_rx_queue_restart(irq->bp->dev, irq->ring_nr);
+               if (err)
+                       netdev_err(irq->bp->dev,
+                                  "RX queue restart failed: err=%d\n", err);
+       }
+       rtnl_unlock();
+}
+
+static void bnxt_irq_affinity_release(struct kref *ref)
+{
+       struct irq_affinity_notify *notify =
+               container_of(ref, struct irq_affinity_notify, kref);
+       struct bnxt_irq *irq;
+
+       irq = container_of(notify, struct bnxt_irq, affinity_notify);
+
+       if (!irq->bp->tph_mode)
+               return;
+
+       if (pcie_tph_set_st_entry(irq->bp->pdev, irq->msix_nr, 0)) {
+               netdev_err(irq->bp->dev,
+                          "Setting ST=0 for MSIX entry %d failed\n",
+                          irq->msix_nr);
+               return;
+       }
+}
+
+static void bnxt_release_irq_notifier(struct bnxt_irq *irq)
+{
+       irq_set_affinity_notifier(irq->vector, NULL);
+}
+
+static void bnxt_register_irq_notifier(struct bnxt *bp, struct bnxt_irq *irq)
+{
+       struct irq_affinity_notify *notify;
+
+       irq->bp = bp;
+
+       /* Nothing to do if TPH is not enabled */
+       if (!bp->tph_mode)
+               return;
+
+       /* Register IRQ affinity notifier */
+       notify = &irq->affinity_notify;
+       notify->irq = irq->vector;
+       notify->notify = bnxt_irq_affinity_notify;
+       notify->release = bnxt_irq_affinity_release;
+
+       irq_set_affinity_notifier(irq->vector, notify);
+}
+
 static void bnxt_free_irq(struct bnxt *bp)
 {
        struct bnxt_irq *irq;
@@ -11373,11 +11453,18 @@ static void bnxt_free_irq(struct bnxt *bp)
                                free_cpumask_var(irq->cpu_mask);
                                irq->have_cpumask = 0;
                        }
+
+                       bnxt_release_irq_notifier(irq);
+
                        free_irq(irq->vector, bp->bnapi[i]);
                }
 
                irq->requested = 0;
        }
+
+       /* Disable TPH support */
+       pcie_disable_tph(bp->pdev);
+       bp->tph_mode = 0;
 }
 
 static int bnxt_request_irq(struct bnxt *bp)
@@ -11397,6 +11484,12 @@ static int bnxt_request_irq(struct bnxt *bp)
 #ifdef CONFIG_RFS_ACCEL
        rmap = bp->dev->rx_cpu_rmap;
 #endif
+
+       /* Enable TPH support as part of IRQ request */
+       rc = pcie_enable_tph(bp->pdev, PCI_TPH_ST_IV_MODE);
+       if (!rc)
+               bp->tph_mode = PCI_TPH_ST_IV_MODE;
+
        for (i = 0, j = 0; i < bp->cp_nr_rings; i++) {
                int map_idx = bnxt_cp_num_to_irq_num(bp, i);
                struct bnxt_irq *irq = &bp->irq_tbl[map_idx];
@@ -11420,8 +11513,11 @@ static int bnxt_request_irq(struct bnxt *bp)
 
                if (zalloc_cpumask_var(&irq->cpu_mask, GFP_KERNEL)) {
                        int numa_node = dev_to_node(&bp->pdev->dev);
+                       u16 tag;
 
                        irq->have_cpumask = 1;
+                       irq->msix_nr = map_idx;
+                       irq->ring_nr = i;
                        cpumask_set_cpu(cpumask_local_spread(i, numa_node),
                                        irq->cpu_mask);
                        rc = irq_update_affinity_hint(irq->vector, irq->cpu_mask);
@@ -11431,6 +11527,16 @@ static int bnxt_request_irq(struct bnxt *bp)
                                            irq->vector);
                                break;
                        }
+
+                       bnxt_register_irq_notifier(bp, irq);
+
+                       /* Init ST table entry */
+                       if (pcie_tph_get_cpu_st(irq->bp->pdev, TPH_MEM_TYPE_VM,
+                                               cpumask_first(irq->cpu_mask),
+                                               &tag))
+                               continue;
+
+                       pcie_tph_set_st_entry(irq->bp->pdev, irq->msix_nr, tag);
                }
        }
        return rc;
index 4e20878e7714935f39985ca07ee5b217519e069d..e85b5ce94f5879cbcffbfc6fa8c910dd596fe249 100644 (file)
@@ -1234,6 +1234,11 @@ struct bnxt_irq {
        u8              have_cpumask:1;
        char            name[IFNAMSIZ + BNXT_IRQ_NAME_EXTRA];
        cpumask_var_t   cpu_mask;
+
+       struct bnxt     *bp;
+       int             msix_nr;
+       int             ring_nr;
+       struct irq_affinity_notify affinity_notify;
 };
 
 #define HWRM_RING_ALLOC_TX     0x1