Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7809592d authored by Michael Chan's avatar Michael Chan Committed by David S. Miller
Browse files

bnxt_en: Enable MSIX early in bnxt_init_one().



To better support the new RDMA driver, we need to move pci_enable_msix()
from bnxt_open() to bnxt_init_one().  This way, MSIX vectors are available
to the RDMA driver whether the network device is up or down.

Part of the existing bnxt_setup_int_mode() function is now refactored into
a new bnxt_init_int_mode().  bnxt_init_int_mode() is called during
bnxt_init_one() to enable MSIX.  The remaining logic in
bnxt_setup_int_mode() to map the IRQs to the completion rings is called
during bnxt_open().

v2: Fixed compile warning when CONFIG_BNXT_SRIOV is not set.

Signed-off-by: default avatarSomnath Kotur <somnath.kotur@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 33c2657e
Loading
Loading
Loading
Loading
+114 −69
Original line number Original line Diff line number Diff line
@@ -4743,6 +4743,80 @@ static int bnxt_trim_rings(struct bnxt *bp, int *rx, int *tx, int max,
	return 0;
	return 0;
}
}


static void bnxt_setup_msix(struct bnxt *bp)
{
	const int len = sizeof(bp->irq_tbl[0].name);
	struct net_device *dev = bp->dev;
	int tcs, i;

	tcs = netdev_get_num_tc(dev);
	if (tcs > 1) {
		bp->tx_nr_rings_per_tc = bp->tx_nr_rings / tcs;
		if (bp->tx_nr_rings_per_tc == 0) {
			netdev_reset_tc(dev);
			bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
		} else {
			int i, off, count;

			bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs;
			for (i = 0; i < tcs; i++) {
				count = bp->tx_nr_rings_per_tc;
				off = i * count;
				netdev_set_tc_queue(dev, i, count, off);
			}
		}
	}

	for (i = 0; i < bp->cp_nr_rings; i++) {
		char *attr;

		if (bp->flags & BNXT_FLAG_SHARED_RINGS)
			attr = "TxRx";
		else if (i < bp->rx_nr_rings)
			attr = "rx";
		else
			attr = "tx";

		snprintf(bp->irq_tbl[i].name, len, "%s-%s-%d", dev->name, attr,
			 i);
		bp->irq_tbl[i].handler = bnxt_msix;
	}
}

static void bnxt_setup_inta(struct bnxt *bp)
{
	const int len = sizeof(bp->irq_tbl[0].name);

	if (netdev_get_num_tc(bp->dev))
		netdev_reset_tc(bp->dev);

	snprintf(bp->irq_tbl[0].name, len, "%s-%s-%d", bp->dev->name, "TxRx",
		 0);
	bp->irq_tbl[0].handler = bnxt_inta;
}

static int bnxt_setup_int_mode(struct bnxt *bp)
{
	int rc;

	if (bp->flags & BNXT_FLAG_USING_MSIX)
		bnxt_setup_msix(bp);
	else
		bnxt_setup_inta(bp);

	rc = bnxt_set_real_num_queues(bp);
	return rc;
}

static unsigned int bnxt_get_max_func_irqs(struct bnxt *bp)
{
#if defined(CONFIG_BNXT_SRIOV)
	if (BNXT_VF(bp))
		return bp->vf.max_irqs;
#endif
	return bp->pf.max_irqs;
}

void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs)
void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs)
{
{
#if defined(CONFIG_BNXT_SRIOV)
#if defined(CONFIG_BNXT_SRIOV)
@@ -4753,16 +4827,12 @@ void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs)
		bp->pf.max_irqs = max_irqs;
		bp->pf.max_irqs = max_irqs;
}
}


static int bnxt_setup_msix(struct bnxt *bp)
static int bnxt_init_msix(struct bnxt *bp)
{
{
	struct msix_entry *msix_ent;
	struct net_device *dev = bp->dev;
	int i, total_vecs, rc = 0, min = 1;
	int i, total_vecs, rc = 0, min = 1;
	const int len = sizeof(bp->irq_tbl[0].name);
	struct msix_entry *msix_ent;

	bp->flags &= ~BNXT_FLAG_USING_MSIX;
	total_vecs = bp->cp_nr_rings;


	total_vecs = bnxt_get_max_func_irqs(bp);
	msix_ent = kcalloc(total_vecs, sizeof(struct msix_entry), GFP_KERNEL);
	msix_ent = kcalloc(total_vecs, sizeof(struct msix_entry), GFP_KERNEL);
	if (!msix_ent)
	if (!msix_ent)
		return -ENOMEM;
		return -ENOMEM;
@@ -4783,8 +4853,10 @@ static int bnxt_setup_msix(struct bnxt *bp)


	bp->irq_tbl = kcalloc(total_vecs, sizeof(struct bnxt_irq), GFP_KERNEL);
	bp->irq_tbl = kcalloc(total_vecs, sizeof(struct bnxt_irq), GFP_KERNEL);
	if (bp->irq_tbl) {
	if (bp->irq_tbl) {
		int tcs;
		for (i = 0; i < total_vecs; i++)
			bp->irq_tbl[i].vector = msix_ent[i].vector;


		bp->total_irqs = total_vecs;
		/* Trim rings based upon num of vectors allocated */
		/* Trim rings based upon num of vectors allocated */
		rc = bnxt_trim_rings(bp, &bp->rx_nr_rings, &bp->tx_nr_rings,
		rc = bnxt_trim_rings(bp, &bp->rx_nr_rings, &bp->tx_nr_rings,
				     total_vecs, min == 1);
				     total_vecs, min == 1);
@@ -4792,43 +4864,10 @@ static int bnxt_setup_msix(struct bnxt *bp)
			goto msix_setup_exit;
			goto msix_setup_exit;


		bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
		bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
		tcs = netdev_get_num_tc(dev);
		bp->cp_nr_rings = (min == 1) ?
		if (tcs > 1) {
				  max_t(int, bp->tx_nr_rings, bp->rx_nr_rings) :
			bp->tx_nr_rings_per_tc = bp->tx_nr_rings / tcs;
				  bp->tx_nr_rings + bp->rx_nr_rings;
			if (bp->tx_nr_rings_per_tc == 0) {
				netdev_reset_tc(dev);
				bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
			} else {
				int i, off, count;

				bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs;
				for (i = 0; i < tcs; i++) {
					count = bp->tx_nr_rings_per_tc;
					off = i * count;
					netdev_set_tc_queue(dev, i, count, off);
				}
			}
		}
		bp->cp_nr_rings = total_vecs;

		for (i = 0; i < bp->cp_nr_rings; i++) {
			char *attr;

			bp->irq_tbl[i].vector = msix_ent[i].vector;
			if (bp->flags & BNXT_FLAG_SHARED_RINGS)
				attr = "TxRx";
			else if (i < bp->rx_nr_rings)
				attr = "rx";
			else
				attr = "tx";


			snprintf(bp->irq_tbl[i].name, len,
				 "%s-%s-%d", dev->name, attr, i);
			bp->irq_tbl[i].handler = bnxt_msix;
		}
		rc = bnxt_set_real_num_queues(bp);
		if (rc)
			goto msix_setup_exit;
	} else {
	} else {
		rc = -ENOMEM;
		rc = -ENOMEM;
		goto msix_setup_exit;
		goto msix_setup_exit;
@@ -4838,52 +4877,54 @@ static int bnxt_setup_msix(struct bnxt *bp)
	return 0;
	return 0;


msix_setup_exit:
msix_setup_exit:
	netdev_err(bp->dev, "bnxt_setup_msix err: %x\n", rc);
	netdev_err(bp->dev, "bnxt_init_msix err: %x\n", rc);
	kfree(bp->irq_tbl);
	bp->irq_tbl = NULL;
	pci_disable_msix(bp->pdev);
	pci_disable_msix(bp->pdev);
	kfree(msix_ent);
	kfree(msix_ent);
	return rc;
	return rc;
}
}


static int bnxt_setup_inta(struct bnxt *bp)
static int bnxt_init_inta(struct bnxt *bp)
{
{
	int rc;
	const int len = sizeof(bp->irq_tbl[0].name);

	if (netdev_get_num_tc(bp->dev))
		netdev_reset_tc(bp->dev);

	bp->irq_tbl = kcalloc(1, sizeof(struct bnxt_irq), GFP_KERNEL);
	bp->irq_tbl = kcalloc(1, sizeof(struct bnxt_irq), GFP_KERNEL);
	if (!bp->irq_tbl) {
	if (!bp->irq_tbl)
		rc = -ENOMEM;
		return -ENOMEM;
		return rc;

	}
	bp->total_irqs = 1;
	bp->rx_nr_rings = 1;
	bp->rx_nr_rings = 1;
	bp->tx_nr_rings = 1;
	bp->tx_nr_rings = 1;
	bp->cp_nr_rings = 1;
	bp->cp_nr_rings = 1;
	bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
	bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
	bp->flags |= BNXT_FLAG_SHARED_RINGS;
	bp->flags |= BNXT_FLAG_SHARED_RINGS;
	bp->irq_tbl[0].vector = bp->pdev->irq;
	bp->irq_tbl[0].vector = bp->pdev->irq;
	snprintf(bp->irq_tbl[0].name, len,
	return 0;
		 "%s-%s-%d", bp->dev->name, "TxRx", 0);
	bp->irq_tbl[0].handler = bnxt_inta;
	rc = bnxt_set_real_num_queues(bp);
	return rc;
}
}


static int bnxt_setup_int_mode(struct bnxt *bp)
static int bnxt_init_int_mode(struct bnxt *bp)
{
{
	int rc = 0;
	int rc = 0;


	if (bp->flags & BNXT_FLAG_MSIX_CAP)
	if (bp->flags & BNXT_FLAG_MSIX_CAP)
		rc = bnxt_setup_msix(bp);
		rc = bnxt_init_msix(bp);


	if (!(bp->flags & BNXT_FLAG_USING_MSIX) && BNXT_PF(bp)) {
	if (!(bp->flags & BNXT_FLAG_USING_MSIX) && BNXT_PF(bp)) {
		/* fallback to INTA */
		/* fallback to INTA */
		rc = bnxt_setup_inta(bp);
		rc = bnxt_init_inta(bp);
	}
	}
	return rc;
	return rc;
}
}


static void bnxt_clear_int_mode(struct bnxt *bp)
{
	if (bp->flags & BNXT_FLAG_USING_MSIX)
		pci_disable_msix(bp->pdev);

	kfree(bp->irq_tbl);
	bp->irq_tbl = NULL;
	bp->flags &= ~BNXT_FLAG_USING_MSIX;
}

static void bnxt_free_irq(struct bnxt *bp)
static void bnxt_free_irq(struct bnxt *bp)
{
{
	struct bnxt_irq *irq;
	struct bnxt_irq *irq;
@@ -4902,10 +4943,6 @@ static void bnxt_free_irq(struct bnxt *bp)
			free_irq(irq->vector, bp->bnapi[i]);
			free_irq(irq->vector, bp->bnapi[i]);
		irq->requested = 0;
		irq->requested = 0;
	}
	}
	if (bp->flags & BNXT_FLAG_USING_MSIX)
		pci_disable_msix(bp->pdev);
	kfree(bp->irq_tbl);
	bp->irq_tbl = NULL;
}
}


static int bnxt_request_irq(struct bnxt *bp)
static int bnxt_request_irq(struct bnxt *bp)
@@ -6695,6 +6732,7 @@ static void bnxt_remove_one(struct pci_dev *pdev)
	cancel_work_sync(&bp->sp_task);
	cancel_work_sync(&bp->sp_task);
	bp->sp_event = 0;
	bp->sp_event = 0;


	bnxt_clear_int_mode(bp);
	bnxt_hwrm_func_drv_unrgtr(bp);
	bnxt_hwrm_func_drv_unrgtr(bp);
	bnxt_free_hwrm_resources(bp);
	bnxt_free_hwrm_resources(bp);
	bnxt_dcb_free(bp);
	bnxt_dcb_free(bp);
@@ -6990,10 +7028,14 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
	if (rc)
	if (rc)
		goto init_err;
		goto init_err;


	rc = register_netdev(dev);
	rc = bnxt_init_int_mode(bp);
	if (rc)
	if (rc)
		goto init_err;
		goto init_err;


	rc = register_netdev(dev);
	if (rc)
		goto init_err_clr_int;

	netdev_info(dev, "%s found at mem %lx, node addr %pM\n",
	netdev_info(dev, "%s found at mem %lx, node addr %pM\n",
		    board_info[ent->driver_data].name,
		    board_info[ent->driver_data].name,
		    (long)pci_resource_start(pdev, 0), dev->dev_addr);
		    (long)pci_resource_start(pdev, 0), dev->dev_addr);
@@ -7002,6 +7044,9 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)


	return 0;
	return 0;


init_err_clr_int:
	bnxt_clear_int_mode(bp);

init_err:
init_err:
	pci_iounmap(pdev, bp->bar0);
	pci_iounmap(pdev, bp->bar0);
	pci_release_regions(pdev);
	pci_release_regions(pdev);
+1 −0
Original line number Original line Diff line number Diff line
@@ -1024,6 +1024,7 @@ struct bnxt {
#define BNXT_STATE_FN_RST_DONE	2
#define BNXT_STATE_FN_RST_DONE	2


	struct bnxt_irq	*irq_tbl;
	struct bnxt_irq	*irq_tbl;
	int			total_irqs;
	u8			mac_addr[ETH_ALEN];
	u8			mac_addr[ETH_ALEN];


#ifdef CONFIG_BNXT_DCB
#ifdef CONFIG_BNXT_DCB