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

Commit 02b52428 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'bnx2x-cnic-bnx2fc-bd-support'



Yuval Mintz says:

====================
bnx2x, cnic, bnx2fc: add support for BD

Commit 230d00eb ("bnx2x: new Multi-function mode - BD") added support
for a new multi-function mode, but it added only the support required by
bnx2x for L2 interfaces.

This adds the required changes to support the new multi-function mode in
the offloaded storage protocols.

Dave,

Please consider applying this series to `net-next'.

Do notice that this involves non-networking driver changes -
but sending this as a single series seemed like the best approach as
we had to have bnx2x changes to support the new functionality.
If this is problematic, please tell us what's the preferred solution here.

Changes from previous versions
------------------------------

 - From v1 - no actual changes; v1 failed to reach netdev so in order to
   keep things in line I've termed this one v2.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ff147028 2971ff67
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -1386,4 +1386,16 @@ void bnx2x_schedule_sp_rtnl(struct bnx2x*, enum sp_rtnl_flag,
 * @state:	OS_DRIVER_STATE_* value reflecting current driver state
 */
void bnx2x_set_os_driver_state(struct bnx2x *bp, u32 state);

/**
 * bnx2x_nvram_read - reads data from nvram [might sleep]
 *
 * @bp:		driver handle
 * @offset:	byte offset in nvram
 * @ret_buf:	pointer to buffer where data is to be stored
 * @buf_size:   Length of 'ret_buf' in bytes
 */
int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf,
		     int buf_size);

#endif /* BNX2X_CMN_H */
+2 −2
Original line number Diff line number Diff line
@@ -1348,7 +1348,7 @@ static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, __be32 *ret_val,
	return rc;
}

static int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf,
int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf,
		     int buf_size)
{
	int rc;
+19 −0
Original line number Diff line number Diff line
@@ -2075,6 +2075,25 @@ enum curr_cfg_method_e {
	CURR_CFG_MET_VENDOR_SPEC = 2,/* e.g. Option ROM, NPAR, O/S Cfg Utils */
};

#define FC_NPIV_WWPN_SIZE 8
#define FC_NPIV_WWNN_SIZE 8
struct bdn_npiv_settings {
	u8 npiv_wwpn[FC_NPIV_WWPN_SIZE];
	u8 npiv_wwnn[FC_NPIV_WWNN_SIZE];
};

struct bdn_fc_npiv_cfg {
	/* hdr used internally by the MFW */
	u32 hdr;
	u32 num_of_npiv;
};

#define MAX_NUMBER_NPIV 64
struct bdn_fc_npiv_tbl {
	struct bdn_fc_npiv_cfg fc_npiv_cfg;
	struct bdn_npiv_settings settings[MAX_NUMBER_NPIV];
};

struct mdump_driver_info {
	u32 epoc;
	u32 drv_ver;
+85 −0
Original line number Diff line number Diff line
@@ -14653,6 +14653,90 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
		rc = -EINVAL;
	}

	/* For storage-only interfaces, change driver state */
	if (IS_MF_SD_STORAGE_PERSONALITY_ONLY(bp)) {
		switch (ctl->drv_state) {
		case DRV_NOP:
			break;
		case DRV_ACTIVE:
			bnx2x_set_os_driver_state(bp,
						  OS_DRIVER_STATE_ACTIVE);
			break;
		case DRV_INACTIVE:
			bnx2x_set_os_driver_state(bp,
						  OS_DRIVER_STATE_DISABLED);
			break;
		case DRV_UNLOADED:
			bnx2x_set_os_driver_state(bp,
						  OS_DRIVER_STATE_NOT_LOADED);
			break;
		default:
		BNX2X_ERR("Unknown cnic driver state: %d\n", ctl->drv_state);
		}
	}

	return rc;
}

static int bnx2x_get_fc_npiv(struct net_device *dev,
			     struct cnic_fc_npiv_tbl *cnic_tbl)
{
	struct bnx2x *bp = netdev_priv(dev);
	struct bdn_fc_npiv_tbl *tbl = NULL;
	u32 offset, entries;
	int rc = -EINVAL;
	int i;

	if (!SHMEM2_HAS(bp, fc_npiv_nvram_tbl_addr[0]))
		goto out;

	DP(BNX2X_MSG_MCP, "About to read the FC-NPIV table\n");

	tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
	if (!tbl) {
		BNX2X_ERR("Failed to allocate fc_npiv table\n");
		goto out;
	}

	offset = SHMEM2_RD(bp, fc_npiv_nvram_tbl_addr[BP_PORT(bp)]);
	DP(BNX2X_MSG_MCP, "Offset of FC-NPIV in NVRAM: %08x\n", offset);

	/* Read the table contents from nvram */
	if (bnx2x_nvram_read(bp, offset, (u8 *)tbl, sizeof(*tbl))) {
		BNX2X_ERR("Failed to read FC-NPIV table\n");
		goto out;
	}

	/* Since bnx2x_nvram_read() returns data in be32, we need to convert
	 * the number of entries back to cpu endianness.
	 */
	entries = tbl->fc_npiv_cfg.num_of_npiv;
	entries = (__force u32)be32_to_cpu((__force __be32)entries);
	tbl->fc_npiv_cfg.num_of_npiv = entries;

	if (!tbl->fc_npiv_cfg.num_of_npiv) {
		DP(BNX2X_MSG_MCP,
		   "No FC-NPIV table [valid, simply not present]\n");
		goto out;
	} else if (tbl->fc_npiv_cfg.num_of_npiv > MAX_NUMBER_NPIV) {
		BNX2X_ERR("FC-NPIV table with bad length 0x%08x\n",
			  tbl->fc_npiv_cfg.num_of_npiv);
		goto out;
	} else {
		DP(BNX2X_MSG_MCP, "Read 0x%08x entries from NVRAM\n",
		   tbl->fc_npiv_cfg.num_of_npiv);
	}

	/* Copy the data into cnic-provided struct */
	cnic_tbl->count = tbl->fc_npiv_cfg.num_of_npiv;
	for (i = 0; i < cnic_tbl->count; i++) {
		memcpy(cnic_tbl->wwpn[i], tbl->settings[i].npiv_wwpn, 8);
		memcpy(cnic_tbl->wwnn[i], tbl->settings[i].npiv_wwnn, 8);
	}

	rc = 0;
out:
	kfree(tbl);
	return rc;
}

@@ -14798,6 +14882,7 @@ static struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
	cp->starting_cid = bnx2x_cid_ilt_lines(bp) * ILT_PAGE_CIDS;
	cp->drv_submit_kwqes_16 = bnx2x_cnic_sp_queue;
	cp->drv_ctl = bnx2x_drv_ctl;
	cp->drv_get_fc_npiv_tbl = bnx2x_get_fc_npiv;
	cp->drv_register_cnic = bnx2x_register_cnic;
	cp->drv_unregister_cnic = bnx2x_unregister_cnic;
	cp->fcoe_init_cid = BNX2X_FCOE_ETH_CID(bp);
+33 −3
Original line number Diff line number Diff line
@@ -192,6 +192,7 @@ static void cnic_ctx_wr(struct cnic_dev *dev, u32 cid_addr, u32 off, u32 val)
	struct drv_ctl_info info;
	struct drv_ctl_io *io = &info.data.io;

	memset(&info, 0, sizeof(struct drv_ctl_info));
	info.cmd = DRV_CTL_CTX_WR_CMD;
	io->cid_addr = cid_addr;
	io->offset = off;
@@ -206,6 +207,7 @@ static void cnic_ctx_tbl_wr(struct cnic_dev *dev, u32 off, dma_addr_t addr)
	struct drv_ctl_info info;
	struct drv_ctl_io *io = &info.data.io;

	memset(&info, 0, sizeof(struct drv_ctl_info));
	info.cmd = DRV_CTL_CTXTBL_WR_CMD;
	io->offset = off;
	io->dma_addr = addr;
@@ -219,6 +221,7 @@ static void cnic_ring_ctl(struct cnic_dev *dev, u32 cid, u32 cl_id, int start)
	struct drv_ctl_info info;
	struct drv_ctl_l2_ring *ring = &info.data.ring;

	memset(&info, 0, sizeof(struct drv_ctl_info));
	if (start)
		info.cmd = DRV_CTL_START_L2_CMD;
	else
@@ -236,6 +239,7 @@ static void cnic_reg_wr_ind(struct cnic_dev *dev, u32 off, u32 val)
	struct drv_ctl_info info;
	struct drv_ctl_io *io = &info.data.io;

	memset(&info, 0, sizeof(struct drv_ctl_info));
	info.cmd = DRV_CTL_IO_WR_CMD;
	io->offset = off;
	io->data = val;
@@ -249,13 +253,14 @@ static u32 cnic_reg_rd_ind(struct cnic_dev *dev, u32 off)
	struct drv_ctl_info info;
	struct drv_ctl_io *io = &info.data.io;

	memset(&info, 0, sizeof(struct drv_ctl_info));
	info.cmd = DRV_CTL_IO_RD_CMD;
	io->offset = off;
	ethdev->drv_ctl(dev->netdev, &info);
	return io->data;
}

static void cnic_ulp_ctl(struct cnic_dev *dev, int ulp_type, bool reg)
static void cnic_ulp_ctl(struct cnic_dev *dev, int ulp_type, bool reg, int state)
{
	struct cnic_local *cp = dev->cnic_priv;
	struct cnic_eth_dev *ethdev = cp->ethdev;
@@ -263,6 +268,7 @@ static void cnic_ulp_ctl(struct cnic_dev *dev, int ulp_type, bool reg)
	struct fcoe_capabilities *fcoe_cap =
		&info.data.register_data.fcoe_features;

	memset(&info, 0, sizeof(struct drv_ctl_info));
	if (reg) {
		info.cmd = DRV_CTL_ULP_REGISTER_CMD;
		if (ulp_type == CNIC_ULP_FCOE && dev->fcoe_cap)
@@ -272,6 +278,7 @@ static void cnic_ulp_ctl(struct cnic_dev *dev, int ulp_type, bool reg)
	}

	info.data.ulp_type = ulp_type;
	info.drv_state = state;
	ethdev->drv_ctl(dev->netdev, &info);
}

@@ -286,6 +293,7 @@ static void cnic_spq_completion(struct cnic_dev *dev, int cmd, u32 count)
	struct cnic_eth_dev *ethdev = cp->ethdev;
	struct drv_ctl_info info;

	memset(&info, 0, sizeof(struct drv_ctl_info));
	info.cmd = cmd;
	info.data.credit.credit_count = count;
	ethdev->drv_ctl(dev->netdev, &info);
@@ -591,7 +599,7 @@ static int cnic_register_device(struct cnic_dev *dev, int ulp_type,

	mutex_unlock(&cnic_lock);

	cnic_ulp_ctl(dev, ulp_type, true);
	cnic_ulp_ctl(dev, ulp_type, true, DRV_ACTIVE);

	return 0;

@@ -636,7 +644,10 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)
	if (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]))
		netdev_warn(dev->netdev, "Failed waiting for ULP up call to complete\n");

	cnic_ulp_ctl(dev, ulp_type, false);
	if (test_bit(ULP_F_INIT, &cp->ulp_flags[ulp_type]))
		cnic_ulp_ctl(dev, ulp_type, false, DRV_UNLOADED);
	else
		cnic_ulp_ctl(dev, ulp_type, false, DRV_INACTIVE);

	return 0;
}
@@ -4267,6 +4278,7 @@ static void cnic_delete_task(struct work_struct *work)

		cnic_ulp_stop_one(cp, CNIC_ULP_ISCSI);

		memset(&info, 0, sizeof(struct drv_ctl_info));
		info.cmd = DRV_CTL_ISCSI_STOPPED_CMD;
		cp->ethdev->drv_ctl(dev->netdev, &info);
	}
@@ -5433,6 +5445,23 @@ static void cnic_free_dev(struct cnic_dev *dev)
	kfree(dev);
}

static int cnic_get_fc_npiv_tbl(struct cnic_dev *dev,
				struct cnic_fc_npiv_tbl *npiv_tbl)
{
	struct cnic_local *cp = dev->cnic_priv;
	struct bnx2x *bp = netdev_priv(dev->netdev);
	int ret;

	if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
		return -EAGAIN;     /* bnx2x is down */

	if (!BNX2X_CHIP_IS_E2_PLUS(bp))
		return -EINVAL;

	ret = cp->ethdev->drv_get_fc_npiv_tbl(dev->netdev, npiv_tbl);
	return ret;
}

static struct cnic_dev *cnic_alloc_dev(struct net_device *dev,
				       struct pci_dev *pdev)
{
@@ -5451,6 +5480,7 @@ static struct cnic_dev *cnic_alloc_dev(struct net_device *dev,
	cdev->register_device = cnic_register_device;
	cdev->unregister_device = cnic_unregister_device;
	cdev->iscsi_nl_msg_recv = cnic_iscsi_nl_msg_recv;
	cdev->get_fc_npiv_tbl = cnic_get_fc_npiv_tbl;

	cp = cdev->cnic_priv;
	cp->dev = cdev;
Loading