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

Commit 1ab4434c authored by Ariel Elior's avatar Ariel Elior Committed by David S. Miller
Browse files

bnx2x: Support probing and removing of VF device



To support probing and removing of a bnx2x virtual function
the following were added:
1. add bnx2x_vfpf.h: defines the VF to PF channel
2. add bnx2x_sriov.h: header for bnx2x SR-IOV functionality
3. enumerate VF hw types (identify VFs)
4. if driving a VF, map VF bar
5. if driving a VF, allocate Vf to PF channel
6. refactor interrupt flows to include VF

Signed-off-by: default avatarAriel Elior <ariele@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7f51c587
Loading
Loading
Loading
Loading
+19 −2
Original line number Original line Diff line number Diff line
@@ -49,6 +49,12 @@
#include "bnx2x_dcb.h"
#include "bnx2x_dcb.h"
#include "bnx2x_stats.h"
#include "bnx2x_stats.h"


enum bnx2x_int_mode {
	BNX2X_INT_MODE_MSIX,
	BNX2X_INT_MODE_INTX,
	BNX2X_INT_MODE_MSI
};

/* error/debug prints */
/* error/debug prints */


#define DRV_MODULE_NAME		"bnx2x"
#define DRV_MODULE_NAME		"bnx2x"
@@ -954,6 +960,9 @@ struct bnx2x_port {
extern struct workqueue_struct *bnx2x_wq;
extern struct workqueue_struct *bnx2x_wq;


#define BNX2X_MAX_NUM_OF_VFS	64
#define BNX2X_MAX_NUM_OF_VFS	64
#define BNX2X_VF_CID_WND	0
#define BNX2X_CIDS_PER_VF	(1 << BNX2X_VF_CID_WND)
#define BNX2X_VF_CIDS		(BNX2X_MAX_NUM_OF_VFS * BNX2X_CIDS_PER_VF)
#define BNX2X_VF_ID_INVALID	0xFF
#define BNX2X_VF_ID_INVALID	0xFF


/*
/*
@@ -1231,6 +1240,10 @@ struct bnx2x {
	  (vn) * ((CHIP_IS_E1x(bp) || (CHIP_MODE_IS_4_PORT(bp))) ? 2  : 1))
	  (vn) * ((CHIP_IS_E1x(bp) || (CHIP_MODE_IS_4_PORT(bp))) ? 2  : 1))
#define BP_FW_MB_IDX(bp)		BP_FW_MB_IDX_VN(bp, BP_VN(bp))
#define BP_FW_MB_IDX(bp)		BP_FW_MB_IDX_VN(bp, BP_VN(bp))


	/* vf pf channel mailbox contains request and response buffers */
	struct bnx2x_vf_mbx_msg	*vf2pf_mbox;
	dma_addr_t		vf2pf_mbox_mapping;

	struct net_device	*dev;
	struct net_device	*dev;
	struct pci_dev		*pdev;
	struct pci_dev		*pdev;


@@ -1318,8 +1331,6 @@ struct bnx2x {
#define DISABLE_MSI_FLAG		(1 << 7)
#define DISABLE_MSI_FLAG		(1 << 7)
#define TPA_ENABLE_FLAG			(1 << 8)
#define TPA_ENABLE_FLAG			(1 << 8)
#define NO_MCP_FLAG			(1 << 9)
#define NO_MCP_FLAG			(1 << 9)

#define BP_NOMCP(bp)			(bp->flags & NO_MCP_FLAG)
#define GRO_ENABLE_FLAG			(1 << 10)
#define GRO_ENABLE_FLAG			(1 << 10)
#define MF_FUNC_DIS			(1 << 11)
#define MF_FUNC_DIS			(1 << 11)
#define OWN_CNIC_IRQ			(1 << 12)
#define OWN_CNIC_IRQ			(1 << 12)
@@ -1330,6 +1341,11 @@ struct bnx2x {
#define BC_SUPPORTS_FCOE_FEATURES	(1 << 19)
#define BC_SUPPORTS_FCOE_FEATURES	(1 << 19)
#define USING_SINGLE_MSIX_FLAG		(1 << 20)
#define USING_SINGLE_MSIX_FLAG		(1 << 20)
#define BC_SUPPORTS_DCBX_MSG_NON_PMF	(1 << 21)
#define BC_SUPPORTS_DCBX_MSG_NON_PMF	(1 << 21)
#define IS_VF_FLAG			(1 << 22)

#define BP_NOMCP(bp)			((bp)->flags & NO_MCP_FLAG)
#define IS_VF(bp)			((bp)->flags & IS_VF_FLAG)
#define IS_PF(bp)			(!((bp)->flags & IS_VF_FLAG))


#define NO_ISCSI(bp)		((bp)->flags & NO_ISCSI_FLAG)
#define NO_ISCSI(bp)		((bp)->flags & NO_ISCSI_FLAG)
#define NO_ISCSI_OOO(bp)	((bp)->flags & NO_ISCSI_OOO_FLAG)
#define NO_ISCSI_OOO(bp)	((bp)->flags & NO_ISCSI_OOO_FLAG)
@@ -1432,6 +1448,7 @@ struct bnx2x {
	u8			igu_sb_cnt;
	u8			igu_sb_cnt;
	u8			min_msix_vec_cnt;
	u8			min_msix_vec_cnt;


	u32			igu_base_addr;
	dma_addr_t		def_status_blk_mapping;
	dma_addr_t		def_status_blk_mapping;


	struct bnx2x_slowpath	*slowpath;
	struct bnx2x_slowpath	*slowpath;
+16 −9
Original line number Original line Diff line number Diff line
@@ -1439,12 +1439,15 @@ void bnx2x_free_irq(struct bnx2x *bp)


int bnx2x_enable_msix(struct bnx2x *bp)
int bnx2x_enable_msix(struct bnx2x *bp)
{
{
	int msix_vec = 0, i, rc, req_cnt;
	int msix_vec = 0, i, rc;


	/* VFs don't have a default status block */
	if (IS_PF(bp)) {
		bp->msix_table[msix_vec].entry = msix_vec;
		bp->msix_table[msix_vec].entry = msix_vec;
		BNX2X_DEV_INFO("msix_table[0].entry = %d (slowpath)\n",
		BNX2X_DEV_INFO("msix_table[0].entry = %d (slowpath)\n",
			       bp->msix_table[0].entry);
			       bp->msix_table[0].entry);
		msix_vec++;
		msix_vec++;
	}


	/* Cnic requires an msix vector for itself */
	/* Cnic requires an msix vector for itself */
	if (CNIC_SUPPORT(bp)) {
	if (CNIC_SUPPORT(bp)) {
@@ -1462,9 +1465,10 @@ int bnx2x_enable_msix(struct bnx2x *bp)
		msix_vec++;
		msix_vec++;
	}
	}


	req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_SUPPORT(bp) + 1;
	DP(BNX2X_MSG_SP, "about to request enable msix with %d vectors\n",
	   msix_vec);


	rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt);
	rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], msix_vec);


	/*
	/*
	 * reconfigure number of tx/rx queues according to available
	 * reconfigure number of tx/rx queues according to available
@@ -1472,7 +1476,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
	 */
	 */
	if (rc >= BNX2X_MIN_MSIX_VEC_CNT(bp)) {
	if (rc >= BNX2X_MIN_MSIX_VEC_CNT(bp)) {
		/* how less vectors we will have? */
		/* how less vectors we will have? */
		int diff = req_cnt - rc;
		int diff = msix_vec - rc;


		BNX2X_DEV_INFO("Trying to use less MSI-X vectors: %d\n", rc);
		BNX2X_DEV_INFO("Trying to use less MSI-X vectors: %d\n", rc);


@@ -3905,7 +3909,10 @@ int bnx2x_alloc_mem_bp(struct bnx2x *bp)
	 * The biggest MSI-X table we might need is as a maximum number of fast
	 * The biggest MSI-X table we might need is as a maximum number of fast
	 * path IGU SBs plus default SB (for PF).
	 * path IGU SBs plus default SB (for PF).
	 */
	 */
	msix_table_size = bp->igu_sb_cnt + 1;
	msix_table_size = bp->igu_sb_cnt;
	if (IS_PF(bp))
		msix_table_size++;
	BNX2X_DEV_INFO("msix_table_size %d\n", msix_table_size);


	/* fp array: RSS plus CNIC related L2 queues */
	/* fp array: RSS plus CNIC related L2 queues */
	fp_array_size = BNX2X_MAX_RSS_COUNT(bp) + CNIC_SUPPORT(bp);
	fp_array_size = BNX2X_MAX_RSS_COUNT(bp) + CNIC_SUPPORT(bp);
+1 −1
Original line number Original line Diff line number Diff line
@@ -863,7 +863,7 @@ static inline void bnx2x_del_all_napi(struct bnx2x *bp)
		netif_napi_del(&bnx2x_fp(bp, i, napi));
		netif_napi_del(&bnx2x_fp(bp, i, napi));
}
}


void bnx2x_set_int_mode(struct bnx2x *bp);
int bnx2x_set_int_mode(struct bnx2x *bp);


static inline void bnx2x_disable_msi(struct bnx2x *bp)
static inline void bnx2x_disable_msi(struct bnx2x *bp)
{
{
+244 −146
Original line number Original line Diff line number Diff line
@@ -59,6 +59,8 @@
#include "bnx2x_init.h"
#include "bnx2x_init.h"
#include "bnx2x_init_ops.h"
#include "bnx2x_init_ops.h"
#include "bnx2x_cmn.h"
#include "bnx2x_cmn.h"
#include "bnx2x_vfpf.h"
#include "bnx2x_sriov.h"
#include "bnx2x_dcb.h"
#include "bnx2x_dcb.h"
#include "bnx2x_sp.h"
#include "bnx2x_sp.h"


@@ -133,39 +135,49 @@ enum bnx2x_board_type {
	BCM57711E,
	BCM57711E,
	BCM57712,
	BCM57712,
	BCM57712_MF,
	BCM57712_MF,
	BCM57712_VF,
	BCM57800,
	BCM57800,
	BCM57800_MF,
	BCM57800_MF,
	BCM57800_VF,
	BCM57810,
	BCM57810,
	BCM57810_MF,
	BCM57810_MF,
	BCM57840_O,
	BCM57810_VF,
	BCM57840_4_10,
	BCM57840_4_10,
	BCM57840_2_20,
	BCM57840_2_20,
	BCM57840_MFO,
	BCM57840_MF,
	BCM57840_MF,
	BCM57840_VF,
	BCM57811,
	BCM57811,
	BCM57811_MF
	BCM57811_MF,
	BCM57840_O,
	BCM57840_MFO,
	BCM57811_VF
};
};


/* indexed by board_type, above */
/* indexed by board_type, above */
static struct {
static struct {
	char *name;
	char *name;
} board_info[] = {
} board_info[] = {
	{ "Broadcom NetXtreme II BCM57710 10 Gigabit PCIe [Everest]" },
	[BCM57710]	= { "Broadcom NetXtreme II BCM57710 10 Gigabit PCIe [Everest]" },
	{ "Broadcom NetXtreme II BCM57711 10 Gigabit PCIe" },
	[BCM57711]	= { "Broadcom NetXtreme II BCM57711 10 Gigabit PCIe" },
	{ "Broadcom NetXtreme II BCM57711E 10 Gigabit PCIe" },
	[BCM57711E]	= { "Broadcom NetXtreme II BCM57711E 10 Gigabit PCIe" },
	{ "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet" },
	[BCM57712]	= { "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet" },
	{ "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function" },
	[BCM57712_MF]	= { "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function" },
	{ "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet" },
	[BCM57712_VF]	= { "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet Virtual Function" },
	{ "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet Multi Function" },
	[BCM57800]	= { "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet" },
	{ "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet" },
	[BCM57800_MF]	= { "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet Multi Function" },
	{ "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function" },
	[BCM57800_VF]	= { "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet Virtual Function" },
	{ "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet" },
	[BCM57810]	= { "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet" },
	{ "Broadcom NetXtreme II BCM57840 10 Gigabit Ethernet" },
	[BCM57810_MF]	= { "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function" },
	{ "Broadcom NetXtreme II BCM57840 20 Gigabit Ethernet" },
	[BCM57810_VF]	= { "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function" },
	{ "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet Multi Function"},
	[BCM57840_4_10]	= { "Broadcom NetXtreme II BCM57840 10 Gigabit Ethernet" },
	{ "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet Multi Function"},
	[BCM57840_2_20]	= { "Broadcom NetXtreme II BCM57840 20 Gigabit Ethernet" },
	{ "Broadcom NetXtreme II BCM57811 10 Gigabit Ethernet"},
	[BCM57840_MF]	= { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet Multi Function" },
	{ "Broadcom NetXtreme II BCM57811 10 Gigabit Ethernet Multi Function"},
	[BCM57840_VF]	= { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function" },
	[BCM57811]	= { "Broadcom NetXtreme II BCM57811 10 Gigabit Ethernet" },
	[BCM57811_MF]	= { "Broadcom NetXtreme II BCM57811 10 Gigabit Ethernet Multi Function" },
	[BCM57840_O]	= { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet" },
	[BCM57840_MFO]	= { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet Multi Function" },
	[BCM57811_VF]	= { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function" }
};
};


#ifndef PCI_DEVICE_ID_NX2_57710
#ifndef PCI_DEVICE_ID_NX2_57710
@@ -7792,41 +7804,49 @@ int bnx2x_setup_leading(struct bnx2x *bp)
 *
 *
 * In case of MSI-X it will also try to enable MSI-X.
 * In case of MSI-X it will also try to enable MSI-X.
 */
 */
void bnx2x_set_int_mode(struct bnx2x *bp)
int bnx2x_set_int_mode(struct bnx2x *bp)
{
{
	int rc = 0;

	if (IS_VF(bp) && int_mode != BNX2X_INT_MODE_MSIX)
		return -EINVAL;

	switch (int_mode) {
	switch (int_mode) {
	case INT_MODE_MSI:
	case BNX2X_INT_MODE_MSIX:
		bnx2x_enable_msi(bp);
		/* attempt to enable msix */
		/* falling through... */
		rc = bnx2x_enable_msix(bp);
	case INT_MODE_INTx:

		bp->num_ethernet_queues = 1;
		/* msix attained */
		bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
		if (!rc)
		BNX2X_DEV_INFO("set number of queues to 1\n");
			return 0;
		break;

	default:
		/* vfs use only msix */
		/* if we can't use MSI-X we only need one fp,
		if (rc && IS_VF(bp))
		 * so try to enable MSI-X with the requested number of fp's
			return rc;
		 * and fallback to MSI or legacy INTx with one fp

		 */
		if (bnx2x_enable_msix(bp) ||
		    bp->flags & USING_SINGLE_MSIX_FLAG) {
		/* failed to enable multiple MSI-X */
		/* failed to enable multiple MSI-X */
		BNX2X_DEV_INFO("Failed to enable multiple MSI-X (%d), set number of queues to %d\n",
		BNX2X_DEV_INFO("Failed to enable multiple MSI-X (%d), set number of queues to %d\n",
			       bp->num_queues,
			       bp->num_queues,
			       1 + bp->num_cnic_queues);
			       1 + bp->num_cnic_queues);


			bp->num_queues = 1 + bp->num_cnic_queues;
		/* falling through... */

	case BNX2X_INT_MODE_MSI:
			/* Try to enable MSI */
			if (!(bp->flags & USING_SINGLE_MSIX_FLAG) &&
			    !(bp->flags & DISABLE_MSI_FLAG))
		bnx2x_enable_msi(bp);
		bnx2x_enable_msi(bp);
		}

		/* falling through... */
	case BNX2X_INT_MODE_INTX:
		bp->num_ethernet_queues = 1;
		bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
		BNX2X_DEV_INFO("set number of queues to 1\n");
		break;
		break;
	default:
		BNX2X_DEV_INFO("unknown value in int_mode module parameter\n");
		return -EINVAL;
	}
	}
	return 0;
}
}


/* must be called prioir to any HW initializations */
/* must be called prior to any HW initializations */
static inline u16 bnx2x_cid_ilt_lines(struct bnx2x *bp)
static inline u16 bnx2x_cid_ilt_lines(struct bnx2x *bp)
{
{
	return L2_ILT_LINES(bp);
	return L2_ILT_LINES(bp);
@@ -11081,9 +11101,13 @@ static int bnx2x_init_bp(struct bnx2x *bp)
	INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
	INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
	INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
	INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
	INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task);
	INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task);
	if (IS_PF(bp)) {
		rc = bnx2x_get_hwinfo(bp);
		rc = bnx2x_get_hwinfo(bp);
		if (rc)
		if (rc)
			return rc;
			return rc;
	} else {
		random_ether_addr(bp->dev->dev_addr);
	}


	bnx2x_set_modes_bitmap(bp);
	bnx2x_set_modes_bitmap(bp);


@@ -11096,7 +11120,7 @@ static int bnx2x_init_bp(struct bnx2x *bp)
	func = BP_FUNC(bp);
	func = BP_FUNC(bp);


	/* need to reset chip if undi was active */
	/* need to reset chip if undi was active */
	if (!BP_NOMCP(bp)) {
	if (IS_PF(bp) && !BP_NOMCP(bp)) {
		/* init fw_seq */
		/* init fw_seq */
		bp->fw_seq =
		bp->fw_seq =
			SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
			SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
@@ -11133,6 +11157,8 @@ static int bnx2x_init_bp(struct bnx2x *bp)
	bp->mrrs = mrrs;
	bp->mrrs = mrrs;


	bp->tx_ring_size = IS_MF_FCOE_AFEX(bp) ? 0 : MAX_TX_AVAIL;
	bp->tx_ring_size = IS_MF_FCOE_AFEX(bp) ? 0 : MAX_TX_AVAIL;
	if (IS_VF(bp))
		bp->rx_ring_size = MAX_RX_AVAIL;


	/* make sure that the numbers are in the right granularity */
	/* make sure that the numbers are in the right granularity */
	bp->tx_ticks = (50 / BNX2X_BTR) * BNX2X_BTR;
	bp->tx_ticks = (50 / BNX2X_BTR) * BNX2X_BTR;
@@ -11161,12 +11187,18 @@ static int bnx2x_init_bp(struct bnx2x *bp)
		bp->cnic_base_cl_id = FP_SB_MAX_E2;
		bp->cnic_base_cl_id = FP_SB_MAX_E2;


	/* multiple tx priority */
	/* multiple tx priority */
	if (CHIP_IS_E1x(bp))
	if (IS_VF(bp))
		bp->max_cos = 1;
	else if (CHIP_IS_E1x(bp))
		bp->max_cos = BNX2X_MULTI_TX_COS_E1X;
		bp->max_cos = BNX2X_MULTI_TX_COS_E1X;
	if (CHIP_IS_E2(bp) || CHIP_IS_E3A0(bp))
	else if (CHIP_IS_E2(bp) || CHIP_IS_E3A0(bp))
		bp->max_cos = BNX2X_MULTI_TX_COS_E2_E3A0;
		bp->max_cos = BNX2X_MULTI_TX_COS_E2_E3A0;
	if (CHIP_IS_E3B0(bp))
	else if (CHIP_IS_E3B0(bp))
		bp->max_cos = BNX2X_MULTI_TX_COS_E3B0;
		bp->max_cos = BNX2X_MULTI_TX_COS_E3B0;
	else
		BNX2X_ERR("unknown chip %x revision %x\n",
			  CHIP_NUM(bp), CHIP_REV(bp));
	BNX2X_DEV_INFO("set bp->max_cos to %d\n", bp->max_cos);


	/* We need at least one default status block for slow-path events,
	/* We need at least one default status block for slow-path events,
	 * second status block for the L2 queue, and a third status block for
	 * second status block for the L2 queue, and a third status block for
@@ -11551,10 +11583,9 @@ static int bnx2x_set_coherency_mask(struct bnx2x *bp)
	return 0;
	return 0;
}
}


static int bnx2x_init_dev(struct pci_dev *pdev, struct net_device *dev,
static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
			  unsigned long board_type)
			  struct net_device *dev, unsigned long board_type)
{
{
	struct bnx2x *bp;
	int rc;
	int rc;
	u32 pci_cfg_dword;
	u32 pci_cfg_dword;
	bool chip_is_e1x = (board_type == BCM57710 ||
	bool chip_is_e1x = (board_type == BCM57710 ||
@@ -11562,11 +11593,9 @@ static int bnx2x_init_dev(struct pci_dev *pdev, struct net_device *dev,
			    board_type == BCM57711E);
			    board_type == BCM57711E);


	SET_NETDEV_DEV(dev, &pdev->dev);
	SET_NETDEV_DEV(dev, &pdev->dev);
	bp = netdev_priv(dev);


	bp->dev = dev;
	bp->dev = dev;
	bp->pdev = pdev;
	bp->pdev = pdev;
	bp->flags = 0;


	rc = pci_enable_device(pdev);
	rc = pci_enable_device(pdev);
	if (rc) {
	if (rc) {
@@ -11582,9 +11611,8 @@ static int bnx2x_init_dev(struct pci_dev *pdev, struct net_device *dev,
		goto err_out_disable;
		goto err_out_disable;
	}
	}


	if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
	if (IS_PF(bp) && !(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
		dev_err(&bp->pdev->dev, "Cannot find second PCI device"
		dev_err(&bp->pdev->dev, "Cannot find second PCI device base address, aborting\n");
		       " base address, aborting\n");
		rc = -ENODEV;
		rc = -ENODEV;
		goto err_out_disable;
		goto err_out_disable;
	}
	}
@@ -11609,6 +11637,7 @@ static int bnx2x_init_dev(struct pci_dev *pdev, struct net_device *dev,
		pci_save_state(pdev);
		pci_save_state(pdev);
	}
	}


	if (IS_PF(bp)) {
		bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
		bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
		if (bp->pm_cap == 0) {
		if (bp->pm_cap == 0) {
			dev_err(&bp->pdev->dev,
			dev_err(&bp->pdev->dev,
@@ -11616,6 +11645,7 @@ static int bnx2x_init_dev(struct pci_dev *pdev, struct net_device *dev,
			rc = -EIO;
			rc = -EIO;
			goto err_out_release;
			goto err_out_release;
		}
		}
	}


	if (!pci_is_pcie(pdev)) {
	if (!pci_is_pcie(pdev)) {
		dev_err(&bp->pdev->dev, "Not PCI Express, aborting\n");
		dev_err(&bp->pdev->dev, "Not PCI Express, aborting\n");
@@ -11665,6 +11695,7 @@ static int bnx2x_init_dev(struct pci_dev *pdev, struct net_device *dev,
	 * Clean the following indirect addresses for all functions since it
	 * Clean the following indirect addresses for all functions since it
	 * is not used by the driver.
	 * is not used by the driver.
	 */
	 */
	if (IS_PF(bp)) {
		REG_WR(bp, PXP2_REG_PGL_ADDR_88_F0, 0);
		REG_WR(bp, PXP2_REG_PGL_ADDR_88_F0, 0);
		REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F0, 0);
		REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F0, 0);
		REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0, 0);
		REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0, 0);
@@ -11677,12 +11708,14 @@ static int bnx2x_init_dev(struct pci_dev *pdev, struct net_device *dev,
			REG_WR(bp, PXP2_REG_PGL_ADDR_94_F1, 0);
			REG_WR(bp, PXP2_REG_PGL_ADDR_94_F1, 0);
		}
		}


	/*
		/* Enable internal target-read (in case we are probed after PF
	 * Enable internal target-read (in case we are probed after PF FLR).
		 * FLR). Must be done prior to any BAR read access. Only for
	 * Must be done prior to any BAR read access. Only for 57712 and up
		 * 57712 and up
		 */
		 */
		if (!chip_is_e1x)
		if (!chip_is_e1x)
		REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
			REG_WR(bp,
			       PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
	}


	dev->watchdog_timeo = TX_TIMEOUT;
	dev->watchdog_timeo = TX_TIMEOUT;


@@ -11734,8 +11767,9 @@ static int bnx2x_init_dev(struct pci_dev *pdev, struct net_device *dev,


static void bnx2x_get_pcie_width_speed(struct bnx2x *bp, int *width, int *speed)
static void bnx2x_get_pcie_width_speed(struct bnx2x *bp, int *width, int *speed)
{
{
	u32 val = REG_RD(bp, PCICFG_OFFSET + PCICFG_LINK_CONTROL);
	u32 val = 0;


	pci_read_config_dword(bp->pdev, PCICFG_LINK_CONTROL, &val);
	*width = (val & PCICFG_LINK_WIDTH) >> PCICFG_LINK_WIDTH_SHIFT;
	*width = (val & PCICFG_LINK_WIDTH) >> PCICFG_LINK_WIDTH_SHIFT;


	/* return value of 1=2.5GHz 2=5GHz */
	/* return value of 1=2.5GHz 2=5GHz */
@@ -12012,10 +12046,10 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp)
 *
 *
 */
 */
static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
				     int cnic_cnt)
				     int cnic_cnt, bool is_vf)
{
{
	int pos;
	int pos, index;
	u16 control;
	u16 control = 0;


	pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
	pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);


@@ -12023,85 +12057,114 @@ static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
	 * If MSI-X is not supported - return number of SBs needed to support
	 * If MSI-X is not supported - return number of SBs needed to support
	 * one fast path queue: one FP queue + SB for CNIC
	 * one fast path queue: one FP queue + SB for CNIC
	 */
	 */
	if (!pos)
	if (!pos) {
		dev_info(&pdev->dev, "no msix capability found\n");
		return 1 + cnic_cnt;
		return 1 + cnic_cnt;
	}
	dev_info(&pdev->dev, "msix capability found\n");


	/*
	/*
	 * The value in the PCI configuration space is the index of the last
	 * The value in the PCI configuration space is the index of the last
	 * entry, namely one less than the actual size of the table, which is
	 * entry, namely one less than the actual size of the table, which is
	 * exactly what we want to return from this function: number of all SBs
	 * exactly what we want to return from this function: number of all SBs
	 * without the default SB.
	 * without the default SB.
	 * For VFs there is no default SB, then we return (index+1).
	 */
	 */
	pci_read_config_word(pdev, pos  + PCI_MSI_FLAGS, &control);
	pci_read_config_word(pdev, pos  + PCI_MSI_FLAGS, &control);
	return control & PCI_MSIX_FLAGS_QSIZE;
}


struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *);
	index = control & PCI_MSIX_FLAGS_QSIZE;


static int bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
	return is_vf ? index + 1 : index;
{
}
	struct net_device *dev = NULL;
	struct bnx2x *bp;
	int pcie_width, pcie_speed;
	int rc, max_non_def_sbs;
	int rx_count, tx_count, rss_count, doorbell_size;
	int cnic_cnt;
	/*
	 * An estimated maximum supported CoS number according to the chip
	 * version.
	 * We will try to roughly estimate the maximum number of CoSes this chip
	 * may support in order to minimize the memory allocated for Tx
	 * netdev_queue's. This number will be accurately calculated during the
	 * initialization of bp->max_cos based on the chip versions AND chip
	 * revision in the bnx2x_init_bp().
	 */
	u8 max_cos_est = 0;


	switch (ent->driver_data) {
static int set_max_cos_est(int chip_id)
{
	switch (chip_id) {
	case BCM57710:
	case BCM57710:
	case BCM57711:
	case BCM57711:
	case BCM57711E:
	case BCM57711E:
		max_cos_est = BNX2X_MULTI_TX_COS_E1X;
		return BNX2X_MULTI_TX_COS_E1X;
		break;

	case BCM57712:
	case BCM57712:
	case BCM57712_MF:
	case BCM57712_MF:
		max_cos_est = BNX2X_MULTI_TX_COS_E2_E3A0;
	case BCM57712_VF:
		break;
		return BNX2X_MULTI_TX_COS_E2_E3A0;

	case BCM57800:
	case BCM57800:
	case BCM57800_MF:
	case BCM57800_MF:
	case BCM57800_VF:
	case BCM57810:
	case BCM57810:
	case BCM57810_MF:
	case BCM57810_MF:
	case BCM57840_O:
	case BCM57840_4_10:
	case BCM57840_4_10:
	case BCM57840_2_20:
	case BCM57840_2_20:
	case BCM57840_O:
	case BCM57840_MFO:
	case BCM57840_MFO:
	case BCM57810_VF:
	case BCM57840_MF:
	case BCM57840_MF:
	case BCM57840_VF:
	case BCM57811:
	case BCM57811:
	case BCM57811_MF:
	case BCM57811_MF:
		max_cos_est = BNX2X_MULTI_TX_COS_E3B0;
	case BCM57811_VF:
		break;
		return BNX2X_MULTI_TX_COS_E3B0;

		return 1;
	default:
	default:
		pr_err("Unknown board_type (%ld), aborting\n",
		pr_err("Unknown board_type (%d), aborting\n", chip_id);
			   ent->driver_data);
		return -ENODEV;
		return -ENODEV;
	}
	}
}

static int set_is_vf(int chip_id)
{
	switch (chip_id) {
	case BCM57712_VF:
	case BCM57800_VF:
	case BCM57810_VF:
	case BCM57840_VF:
	case BCM57811_VF:
		return true;
	default:
		return false;
	}
}

struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev);

static int bnx2x_init_one(struct pci_dev *pdev,
				    const struct pci_device_id *ent)
{
	struct net_device *dev = NULL;
	struct bnx2x *bp;
	int pcie_width, pcie_speed;
	int rc, max_non_def_sbs;
	int rx_count, tx_count, rss_count, doorbell_size;
	int max_cos_est;
	bool is_vf;
	int cnic_cnt;


	cnic_cnt = 1;
	/* An estimated maximum supported CoS number according to the chip
	max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev, cnic_cnt);
	 * version.
	 * We will try to roughly estimate the maximum number of CoSes this chip
	 * may support in order to minimize the memory allocated for Tx
	 * netdev_queue's. This number will be accurately calculated during the
	 * initialization of bp->max_cos based on the chip versions AND chip
	 * revision in the bnx2x_init_bp().
	 */
	max_cos_est = set_max_cos_est(ent->driver_data);
	if (max_cos_est < 0)
		return max_cos_est;
	is_vf = set_is_vf(ent->driver_data);
	cnic_cnt = is_vf ? 0 : 1;


	WARN_ON(!max_non_def_sbs);
	max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev, cnic_cnt, is_vf);


	/* Maximum number of RSS queues: one IGU SB goes to CNIC */
	/* Maximum number of RSS queues: one IGU SB goes to CNIC */
	rss_count = max_non_def_sbs - cnic_cnt;
	rss_count = is_vf ? 1 : max_non_def_sbs - cnic_cnt;

	if (rss_count < 1)
		return -EINVAL;


	/* Maximum number of netdev Rx queues: RSS + FCoE L2 */
	/* Maximum number of netdev Rx queues: RSS + FCoE L2 */
	rx_count = rss_count + cnic_cnt;
	rx_count = rss_count + cnic_cnt;


	/*
	/* Maximum number of netdev Tx queues:
	 * Maximum number of netdev Tx queues:
	 * Maximum TSS queues * Maximum supported number of CoS  + FCoE L2
	 * Maximum TSS queues * Maximum supported number of CoS  + FCoE L2
	 */
	 */
	tx_count = rss_count * max_cos_est + cnic_cnt;
	tx_count = rss_count * max_cos_est + cnic_cnt;
@@ -12113,22 +12176,28 @@ static int bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)


	bp = netdev_priv(dev);
	bp = netdev_priv(dev);


	bp->flags = 0;
	if (is_vf)
		bp->flags |= IS_VF_FLAG;

	bp->igu_sb_cnt = max_non_def_sbs;
	bp->igu_sb_cnt = max_non_def_sbs;
	bp->igu_base_addr = IS_VF(bp) ? PXP_VF_ADDR_IGU_START : BAR_IGU_INTMEM;
	bp->msg_enable = debug;
	bp->msg_enable = debug;
	bp->cnic_support = cnic_cnt;
	bp->cnic_support = cnic_cnt;
	bp->cnic_probe = bnx2x_cnic_probe;
	bp->cnic_probe = bnx2x_cnic_probe;


	pci_set_drvdata(pdev, dev);
	pci_set_drvdata(pdev, dev);


	rc = bnx2x_init_dev(pdev, dev, ent->driver_data);
	rc = bnx2x_init_dev(bp, pdev, dev, ent->driver_data);
	if (rc < 0) {
	if (rc < 0) {
		free_netdev(dev);
		free_netdev(dev);
		return rc;
		return rc;
	}
	}


	BNX2X_DEV_INFO("This is a %s function\n",
		       IS_PF(bp) ? "physical" : "virtual");
	BNX2X_DEV_INFO("Cnic support is %s\n", CNIC_SUPPORT(bp) ? "on" : "off");
	BNX2X_DEV_INFO("Cnic support is %s\n", CNIC_SUPPORT(bp) ? "on" : "off");
	BNX2X_DEV_INFO("max_non_def_sbs %d\n", max_non_def_sbs);
	BNX2X_DEV_INFO("Max num of status blocks %d\n", max_non_def_sbs);

	BNX2X_DEV_INFO("Allocated netdev with %d tx and %d rx queues\n",
	BNX2X_DEV_INFO("Allocated netdev with %d tx and %d rx queues\n",
			  tx_count, rx_count);
			  tx_count, rx_count);


@@ -12136,10 +12205,18 @@ static int bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
	if (rc)
	if (rc)
		goto init_one_exit;
		goto init_one_exit;


	/*
	/* Map doorbells here as we need the real value of bp->max_cos which
	 * Map doorbels here as we need the real value of bp->max_cos which
	 * is initialized in bnx2x_init_bp() to determine the number of
	 * is initialized in bnx2x_init_bp().
	 * l2 connections.
	 */
	 */
	if (IS_VF(bp)) {
		/* vf doorbells are embedded within the regview */
		bp->doorbells = bp->regview + PXP_VF_ADDR_DB_START;

		/* allocate vf2pf mailbox for vf to pf channel */
		BNX2X_PCI_ALLOC(bp->vf2pf_mbox, &bp->vf2pf_mbox_mapping,
				sizeof(struct bnx2x_vf_mbx_msg));
	} else {
		doorbell_size = BNX2X_L2_MAX_CID(bp) * (1 << BNX2X_DB_SHIFT);
		doorbell_size = BNX2X_L2_MAX_CID(bp) * (1 << BNX2X_DB_SHIFT);
		if (doorbell_size > pci_resource_len(pdev, 2)) {
		if (doorbell_size > pci_resource_len(pdev, 2)) {
			dev_err(&bp->pdev->dev,
			dev_err(&bp->pdev->dev,
@@ -12149,6 +12226,7 @@ static int bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
		}
		}
		bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
		bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
						doorbell_size);
						doorbell_size);
	}
	if (!bp->doorbells) {
	if (!bp->doorbells) {
		dev_err(&bp->pdev->dev,
		dev_err(&bp->pdev->dev,
			"Cannot map doorbell space, aborting\n");
			"Cannot map doorbell space, aborting\n");
@@ -12158,6 +12236,7 @@ static int bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)


	/* calc qm_cid_count */
	/* calc qm_cid_count */
	bp->qm_cid_count = bnx2x_set_qm_cid_count(bp);
	bp->qm_cid_count = bnx2x_set_qm_cid_count(bp);
	BNX2X_DEV_INFO("qm_cid_count %d\n", bp->qm_cid_count);


	/* disable FCOE L2 queue for E1x*/
	/* disable FCOE L2 queue for E1x*/
	if (CHIP_IS_E1x(bp))
	if (CHIP_IS_E1x(bp))
@@ -12179,13 +12258,19 @@ static int bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
	/* Configure interrupt mode: try to enable MSI-X/MSI if
	/* Configure interrupt mode: try to enable MSI-X/MSI if
	 * needed.
	 * needed.
	 */
	 */
	bnx2x_set_int_mode(bp);
	rc = bnx2x_set_int_mode(bp);
	if (rc) {
		dev_err(&pdev->dev, "Cannot set interrupts\n");
		goto init_one_exit;
	}


	/* register the net device */
	rc = register_netdev(dev);
	rc = register_netdev(dev);
	if (rc) {
	if (rc) {
		dev_err(&pdev->dev, "Cannot register net device\n");
		dev_err(&pdev->dev, "Cannot register net device\n");
		goto init_one_exit;
		goto init_one_exit;
	}
	}
	BNX2X_DEV_INFO("device name after netdev register %s\n", dev->name);




	if (!NO_FCOE(bp)) {
	if (!NO_FCOE(bp)) {
@@ -12196,6 +12281,8 @@ static int bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
	}
	}


	bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
	bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
	BNX2X_DEV_INFO("got pcie width %d and speed %d\n",
		       pcie_width, pcie_speed);


	BNX2X_DEV_INFO(
	BNX2X_DEV_INFO(
		"%s (%c%d) PCI-E x%d %s found at mem %lx, IRQ %d, node addr %pM\n",
		"%s (%c%d) PCI-E x%d %s found at mem %lx, IRQ %d, node addr %pM\n",
@@ -12209,11 +12296,16 @@ static int bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)


	return 0;
	return 0;


alloc_mem_err:
	BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping,
		       sizeof(struct bnx2x_vf_mbx_msg));
	rc = -ENOMEM;

init_one_exit:
init_one_exit:
	if (bp->regview)
	if (bp->regview)
		iounmap(bp->regview);
		iounmap(bp->regview);


	if (bp->doorbells)
	if (IS_PF(bp) && bp->doorbells)
		iounmap(bp->doorbells);
		iounmap(bp->doorbells);


	free_netdev(dev);
	free_netdev(dev);
@@ -12253,12 +12345,14 @@ static void bnx2x_remove_one(struct pci_dev *pdev)
	unregister_netdev(dev);
	unregister_netdev(dev);


	/* Power on: we can't let PCI layer write to us while we are in D3 */
	/* Power on: we can't let PCI layer write to us while we are in D3 */
	if (IS_PF(bp))
		bnx2x_set_power_state(bp, PCI_D0);
		bnx2x_set_power_state(bp, PCI_D0);


	/* Disable MSI/MSI-X */
	/* Disable MSI/MSI-X */
	bnx2x_disable_msi(bp);
	bnx2x_disable_msi(bp);


	/* Power off */
	/* Power off */
	if (IS_PF(bp))
		bnx2x_set_power_state(bp, PCI_D3hot);
		bnx2x_set_power_state(bp, PCI_D3hot);


	/* Make sure RESET task is not scheduled before continuing */
	/* Make sure RESET task is not scheduled before continuing */
@@ -12267,11 +12361,15 @@ static void bnx2x_remove_one(struct pci_dev *pdev)
	if (bp->regview)
	if (bp->regview)
		iounmap(bp->regview);
		iounmap(bp->regview);


	/* for vf doorbells are part of the regview and were unmapped along with
	 * it. FW is only loaded by PF.
	 */
	if (IS_PF(bp)) {
		if (bp->doorbells)
		if (bp->doorbells)
			iounmap(bp->doorbells);
			iounmap(bp->doorbells);


		bnx2x_release_firmware(bp);
		bnx2x_release_firmware(bp);

	}
	bnx2x_free_mem_bp(bp);
	bnx2x_free_mem_bp(bp);


	free_netdev(dev);
	free_netdev(dev);
+9 −0
Original line number Original line Diff line number Diff line
@@ -6554,6 +6554,15 @@
	(7L<<ME_REG_ABS_PF_NUM_SHIFT) /* Absolute PF Num */
	(7L<<ME_REG_ABS_PF_NUM_SHIFT) /* Absolute PF Num */




#define PXP_VF_ADDR_IGU_START				0
#define PXP_VF_ADDR_IGU_SIZE				0x3000
#define PXP_VF_ADDR_IGU_END\
	((PXP_VF_ADDR_IGU_START) + (PXP_VF_ADDR_IGU_SIZE) - 1)
#define PXP_VF_ADDR_DB_START				0x7c00
#define PXP_VF_ADDR_DB_SIZE				0x200
#define PXP_VF_ADDR_DB_END\
	((PXP_VF_ADDR_DB_START) + (PXP_VF_ADDR_DB_SIZE) - 1)

#define MDIO_REG_BANK_CL73_IEEEB0	0x0
#define MDIO_REG_BANK_CL73_IEEEB0	0x0
#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL	0x0
#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL	0x0
#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN	0x0200
#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN	0x0200
Loading