Commit 1a3d9424 authored by Yuval Mintz's avatar Yuval Mintz Committed by David S. Miller
Browse files

bnx2x: Fix vlan credit issues for VFs



Starting with commit 2dc33bbc "bnx2x: Remove the sriov VFOP mechanism",
the bnx2x started enforcing vlan credits for all vlan configurations.
This exposed 2 issues:
  - Vlan credits are not returned once a VF is removed; this causes a leak
    of credits, and eventually will lead to VFs with no vlan credits.
  - A vlan credit must be set aside for the Hypervisor to use, and should
    not be visible to the VF.

Although linux VFs at the moment do not support vlan configuration [from the
VF side] which causes them to be resilient to this sort of issue, Windows VF
over linux hypervisors might fail to load as the vlan credits become depleted.

Signed-off-by: default avatarYuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: default avatarAriel Elior <Ariel.Elior@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e2a367f8
Loading
Loading
Loading
Loading
+34 −10
Original line number Diff line number Diff line
@@ -427,7 +427,9 @@ static int bnx2x_vf_mac_vlan_config(struct bnx2x *bp,
	if (filter->add && filter->type == BNX2X_VF_FILTER_VLAN &&
	    (atomic_read(&bnx2x_vfq(vf, qid, vlan_count)) >=
	     vf_vlan_rules_cnt(vf))) {
		BNX2X_ERR("No credits for vlan\n");
		BNX2X_ERR("No credits for vlan [%d >= %d]\n",
			  atomic_read(&bnx2x_vfq(vf, qid, vlan_count)),
			  vf_vlan_rules_cnt(vf));
		return -ENOMEM;
	}

@@ -837,6 +839,29 @@ int bnx2x_vf_flr_clnup_epilog(struct bnx2x *bp, u8 abs_vfid)
	return 0;
}

static void bnx2x_iov_re_set_vlan_filters(struct bnx2x *bp,
					  struct bnx2x_virtf *vf,
					  int new)
{
	int num = vf_vlan_rules_cnt(vf);
	int diff = new - num;
	bool rc = true;

	DP(BNX2X_MSG_IOV, "vf[%d] - %d vlan filter credits [previously %d]\n",
	   vf->abs_vfid, new, num);

	if (diff > 0)
		rc = bp->vlans_pool.get(&bp->vlans_pool, diff);
	else if (diff < 0)
		rc = bp->vlans_pool.put(&bp->vlans_pool, -diff);

	if (rc)
		vf_vlan_rules_cnt(vf) = new;
	else
		DP(BNX2X_MSG_IOV, "vf[%d] - Failed to configure vlan filter credits change\n",
		   vf->abs_vfid);
}

/* must be called after the number of PF queues and the number of VFs are
 * both known
 */
@@ -854,9 +879,11 @@ bnx2x_iov_static_resc(struct bnx2x *bp, struct bnx2x_virtf *vf)
	resc->num_mac_filters = 1;

	/* divvy up vlan rules */
	bnx2x_iov_re_set_vlan_filters(bp, vf, 0);
	vlan_count = bp->vlans_pool.check(&bp->vlans_pool);
	vlan_count = 1 << ilog2(vlan_count);
	resc->num_vlan_filters = vlan_count / BNX2X_NR_VIRTFN(bp);
	bnx2x_iov_re_set_vlan_filters(bp, vf,
				      vlan_count / BNX2X_NR_VIRTFN(bp));

	/* no real limitation */
	resc->num_mc_filters = 0;
@@ -1478,10 +1505,6 @@ int bnx2x_iov_nic_init(struct bnx2x *bp)
		bnx2x_iov_static_resc(bp, vf);

		/* queues are initialized during VF-ACQUIRE */

		/* reserve the vf vlan credit */
		bp->vlans_pool.get(&bp->vlans_pool, vf_vlan_rules_cnt(vf));

		vf->filter_state = 0;
		vf->sp_cl_id = bnx2x_fp(bp, 0, cl_id);

@@ -1912,11 +1935,12 @@ int bnx2x_vf_chk_avail_resc(struct bnx2x *bp, struct bnx2x_virtf *vf,
	u8 rxq_cnt = vf_rxq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf);
	u8 txq_cnt = vf_txq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf);

	/* Save a vlan filter for the Hypervisor */
	return ((req_resc->num_rxqs <= rxq_cnt) &&
		(req_resc->num_txqs <= txq_cnt) &&
		(req_resc->num_sbs <= vf_sb_count(vf))   &&
		(req_resc->num_mac_filters <= vf_mac_rules_cnt(vf)) &&
		(req_resc->num_vlan_filters <= vf_vlan_rules_cnt(vf)));
		(req_resc->num_vlan_filters <= vf_vlan_rules_visible_cnt(vf)));
}

/* CORE VF API */
@@ -1972,14 +1996,14 @@ int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
	vf_txq_count(vf) = resc->num_txqs ? : bnx2x_vf_max_queue_cnt(bp, vf);
	if (resc->num_mac_filters)
		vf_mac_rules_cnt(vf) = resc->num_mac_filters;
	if (resc->num_vlan_filters)
		vf_vlan_rules_cnt(vf) = resc->num_vlan_filters;
	/* Add an additional vlan filter credit for the hypervisor */
	bnx2x_iov_re_set_vlan_filters(bp, vf, resc->num_vlan_filters + 1);

	DP(BNX2X_MSG_IOV,
	   "Fulfilling vf request: sb count %d, tx_count %d, rx_count %d, mac_rules_count %d, vlan_rules_count %d\n",
	   vf_sb_count(vf), vf_rxq_count(vf),
	   vf_txq_count(vf), vf_mac_rules_cnt(vf),
	   vf_vlan_rules_cnt(vf));
	   vf_vlan_rules_visible_cnt(vf));

	/* Initialize the queues */
	if (!vf->vfqs) {
+2 −0
Original line number Diff line number Diff line
@@ -159,6 +159,8 @@ struct bnx2x_virtf {
#define vf_mac_rules_cnt(vf)		((vf)->alloc_resc.num_mac_filters)
#define vf_vlan_rules_cnt(vf)		((vf)->alloc_resc.num_vlan_filters)
#define vf_mc_rules_cnt(vf)		((vf)->alloc_resc.num_mc_filters)
	/* Hide a single vlan filter credit for the hypervisor */
#define vf_vlan_rules_visible_cnt(vf)	(vf_vlan_rules_cnt(vf) - 1)

	u8 sb_count;	/* actual number of SBs */
	u8 igu_base_id;	/* base igu status block id */
+1 −1
Original line number Diff line number Diff line
@@ -1163,7 +1163,7 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
			bnx2x_vf_max_queue_cnt(bp, vf);
		resc->num_sbs = vf_sb_count(vf);
		resc->num_mac_filters = vf_mac_rules_cnt(vf);
		resc->num_vlan_filters = vf_vlan_rules_cnt(vf);
		resc->num_vlan_filters = vf_vlan_rules_visible_cnt(vf);
		resc->num_mc_filters = 0;

		if (status == PFVF_STATUS_SUCCESS) {