Commit c214410c authored by Manoj Panicker's avatar Manoj Panicker Committed by Jakub Kicinski
Browse files

bnxt_en: Add TPH support in BNXT driver



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: default avatarSomnath Kotur <somnath.kotur@broadcom.com>
Signed-off-by: default avatarSomnath Kotur <somnath.kotur@broadcom.com>
Co-developed-by: default avatarWei Huang <wei.huang2@amd.com>
Signed-off-by: default avatarWei Huang <wei.huang2@amd.com>
Signed-off-by: default avatarManoj Panicker <manoj.panicker2@amd.com>
Reviewed-by: default avatarAjit Khaparde <ajit.khaparde@broadcom.com>
Reviewed-by: default avatarAndy Gospodarek <andrew.gospodarek@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Link: https://patch.msgid.link/20250213011240.1640031-12-michael.chan@broadcom.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent fe96d717
Loading
Loading
Loading
Loading
+106 −0
Original line number Diff line number Diff line
@@ -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 @@ static int bnxt_tx_queue_start(struct bnxt *bp, int idx)
	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;
+5 −0
Original line number Diff line number Diff line
@@ -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