diff options
author | Yuval Mintz <Yuval.Mintz@qlogic.com> | 2014-04-24 12:29:53 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-04-26 12:15:27 -0400 |
commit | 1a3d94240bc5e969e7e8cef661fbad24296ba36f (patch) | |
tree | 5ce6fccec942f80313703c7171e2938f85b5dbf9 | |
parent | e2a367f8e3c2afd5cfd5f0892844c74960ecc031 (diff) |
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: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: Ariel Elior <Ariel.Elior@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 44 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 2 |
3 files changed, 37 insertions, 11 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 046c9cca0072..eefe8f528309 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | |||
@@ -427,7 +427,9 @@ static int bnx2x_vf_mac_vlan_config(struct bnx2x *bp, | |||
427 | if (filter->add && filter->type == BNX2X_VF_FILTER_VLAN && | 427 | if (filter->add && filter->type == BNX2X_VF_FILTER_VLAN && |
428 | (atomic_read(&bnx2x_vfq(vf, qid, vlan_count)) >= | 428 | (atomic_read(&bnx2x_vfq(vf, qid, vlan_count)) >= |
429 | vf_vlan_rules_cnt(vf))) { | 429 | vf_vlan_rules_cnt(vf))) { |
430 | BNX2X_ERR("No credits for vlan\n"); | 430 | BNX2X_ERR("No credits for vlan [%d >= %d]\n", |
431 | atomic_read(&bnx2x_vfq(vf, qid, vlan_count)), | ||
432 | vf_vlan_rules_cnt(vf)); | ||
431 | return -ENOMEM; | 433 | return -ENOMEM; |
432 | } | 434 | } |
433 | 435 | ||
@@ -837,6 +839,29 @@ int bnx2x_vf_flr_clnup_epilog(struct bnx2x *bp, u8 abs_vfid) | |||
837 | return 0; | 839 | return 0; |
838 | } | 840 | } |
839 | 841 | ||
842 | static void bnx2x_iov_re_set_vlan_filters(struct bnx2x *bp, | ||
843 | struct bnx2x_virtf *vf, | ||
844 | int new) | ||
845 | { | ||
846 | int num = vf_vlan_rules_cnt(vf); | ||
847 | int diff = new - num; | ||
848 | bool rc = true; | ||
849 | |||
850 | DP(BNX2X_MSG_IOV, "vf[%d] - %d vlan filter credits [previously %d]\n", | ||
851 | vf->abs_vfid, new, num); | ||
852 | |||
853 | if (diff > 0) | ||
854 | rc = bp->vlans_pool.get(&bp->vlans_pool, diff); | ||
855 | else if (diff < 0) | ||
856 | rc = bp->vlans_pool.put(&bp->vlans_pool, -diff); | ||
857 | |||
858 | if (rc) | ||
859 | vf_vlan_rules_cnt(vf) = new; | ||
860 | else | ||
861 | DP(BNX2X_MSG_IOV, "vf[%d] - Failed to configure vlan filter credits change\n", | ||
862 | vf->abs_vfid); | ||
863 | } | ||
864 | |||
840 | /* must be called after the number of PF queues and the number of VFs are | 865 | /* must be called after the number of PF queues and the number of VFs are |
841 | * both known | 866 | * both known |
842 | */ | 867 | */ |
@@ -854,9 +879,11 @@ bnx2x_iov_static_resc(struct bnx2x *bp, struct bnx2x_virtf *vf) | |||
854 | resc->num_mac_filters = 1; | 879 | resc->num_mac_filters = 1; |
855 | 880 | ||
856 | /* divvy up vlan rules */ | 881 | /* divvy up vlan rules */ |
882 | bnx2x_iov_re_set_vlan_filters(bp, vf, 0); | ||
857 | vlan_count = bp->vlans_pool.check(&bp->vlans_pool); | 883 | vlan_count = bp->vlans_pool.check(&bp->vlans_pool); |
858 | vlan_count = 1 << ilog2(vlan_count); | 884 | vlan_count = 1 << ilog2(vlan_count); |
859 | resc->num_vlan_filters = vlan_count / BNX2X_NR_VIRTFN(bp); | 885 | bnx2x_iov_re_set_vlan_filters(bp, vf, |
886 | vlan_count / BNX2X_NR_VIRTFN(bp)); | ||
860 | 887 | ||
861 | /* no real limitation */ | 888 | /* no real limitation */ |
862 | resc->num_mc_filters = 0; | 889 | resc->num_mc_filters = 0; |
@@ -1478,10 +1505,6 @@ int bnx2x_iov_nic_init(struct bnx2x *bp) | |||
1478 | bnx2x_iov_static_resc(bp, vf); | 1505 | bnx2x_iov_static_resc(bp, vf); |
1479 | 1506 | ||
1480 | /* queues are initialized during VF-ACQUIRE */ | 1507 | /* queues are initialized during VF-ACQUIRE */ |
1481 | |||
1482 | /* reserve the vf vlan credit */ | ||
1483 | bp->vlans_pool.get(&bp->vlans_pool, vf_vlan_rules_cnt(vf)); | ||
1484 | |||
1485 | vf->filter_state = 0; | 1508 | vf->filter_state = 0; |
1486 | vf->sp_cl_id = bnx2x_fp(bp, 0, cl_id); | 1509 | vf->sp_cl_id = bnx2x_fp(bp, 0, cl_id); |
1487 | 1510 | ||
@@ -1912,11 +1935,12 @@ int bnx2x_vf_chk_avail_resc(struct bnx2x *bp, struct bnx2x_virtf *vf, | |||
1912 | u8 rxq_cnt = vf_rxq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf); | 1935 | u8 rxq_cnt = vf_rxq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf); |
1913 | u8 txq_cnt = vf_txq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf); | 1936 | u8 txq_cnt = vf_txq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf); |
1914 | 1937 | ||
1938 | /* Save a vlan filter for the Hypervisor */ | ||
1915 | return ((req_resc->num_rxqs <= rxq_cnt) && | 1939 | return ((req_resc->num_rxqs <= rxq_cnt) && |
1916 | (req_resc->num_txqs <= txq_cnt) && | 1940 | (req_resc->num_txqs <= txq_cnt) && |
1917 | (req_resc->num_sbs <= vf_sb_count(vf)) && | 1941 | (req_resc->num_sbs <= vf_sb_count(vf)) && |
1918 | (req_resc->num_mac_filters <= vf_mac_rules_cnt(vf)) && | 1942 | (req_resc->num_mac_filters <= vf_mac_rules_cnt(vf)) && |
1919 | (req_resc->num_vlan_filters <= vf_vlan_rules_cnt(vf))); | 1943 | (req_resc->num_vlan_filters <= vf_vlan_rules_visible_cnt(vf))); |
1920 | } | 1944 | } |
1921 | 1945 | ||
1922 | /* CORE VF API */ | 1946 | /* CORE VF API */ |
@@ -1972,14 +1996,14 @@ int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf, | |||
1972 | vf_txq_count(vf) = resc->num_txqs ? : bnx2x_vf_max_queue_cnt(bp, vf); | 1996 | vf_txq_count(vf) = resc->num_txqs ? : bnx2x_vf_max_queue_cnt(bp, vf); |
1973 | if (resc->num_mac_filters) | 1997 | if (resc->num_mac_filters) |
1974 | vf_mac_rules_cnt(vf) = resc->num_mac_filters; | 1998 | vf_mac_rules_cnt(vf) = resc->num_mac_filters; |
1975 | if (resc->num_vlan_filters) | 1999 | /* Add an additional vlan filter credit for the hypervisor */ |
1976 | vf_vlan_rules_cnt(vf) = resc->num_vlan_filters; | 2000 | bnx2x_iov_re_set_vlan_filters(bp, vf, resc->num_vlan_filters + 1); |
1977 | 2001 | ||
1978 | DP(BNX2X_MSG_IOV, | 2002 | DP(BNX2X_MSG_IOV, |
1979 | "Fulfilling vf request: sb count %d, tx_count %d, rx_count %d, mac_rules_count %d, vlan_rules_count %d\n", | 2003 | "Fulfilling vf request: sb count %d, tx_count %d, rx_count %d, mac_rules_count %d, vlan_rules_count %d\n", |
1980 | vf_sb_count(vf), vf_rxq_count(vf), | 2004 | vf_sb_count(vf), vf_rxq_count(vf), |
1981 | vf_txq_count(vf), vf_mac_rules_cnt(vf), | 2005 | vf_txq_count(vf), vf_mac_rules_cnt(vf), |
1982 | vf_vlan_rules_cnt(vf)); | 2006 | vf_vlan_rules_visible_cnt(vf)); |
1983 | 2007 | ||
1984 | /* Initialize the queues */ | 2008 | /* Initialize the queues */ |
1985 | if (!vf->vfqs) { | 2009 | if (!vf->vfqs) { |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index bb16c4b5c2af..6929adba52f9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | |||
@@ -159,6 +159,8 @@ struct bnx2x_virtf { | |||
159 | #define vf_mac_rules_cnt(vf) ((vf)->alloc_resc.num_mac_filters) | 159 | #define vf_mac_rules_cnt(vf) ((vf)->alloc_resc.num_mac_filters) |
160 | #define vf_vlan_rules_cnt(vf) ((vf)->alloc_resc.num_vlan_filters) | 160 | #define vf_vlan_rules_cnt(vf) ((vf)->alloc_resc.num_vlan_filters) |
161 | #define vf_mc_rules_cnt(vf) ((vf)->alloc_resc.num_mc_filters) | 161 | #define vf_mc_rules_cnt(vf) ((vf)->alloc_resc.num_mc_filters) |
162 | /* Hide a single vlan filter credit for the hypervisor */ | ||
163 | #define vf_vlan_rules_visible_cnt(vf) (vf_vlan_rules_cnt(vf) - 1) | ||
162 | 164 | ||
163 | u8 sb_count; /* actual number of SBs */ | 165 | u8 sb_count; /* actual number of SBs */ |
164 | u8 igu_base_id; /* base igu status block id */ | 166 | u8 igu_base_id; /* base igu status block id */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index 0622884596b2..0c067e8564dd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | |||
@@ -1163,7 +1163,7 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf, | |||
1163 | bnx2x_vf_max_queue_cnt(bp, vf); | 1163 | bnx2x_vf_max_queue_cnt(bp, vf); |
1164 | resc->num_sbs = vf_sb_count(vf); | 1164 | resc->num_sbs = vf_sb_count(vf); |
1165 | resc->num_mac_filters = vf_mac_rules_cnt(vf); | 1165 | resc->num_mac_filters = vf_mac_rules_cnt(vf); |
1166 | resc->num_vlan_filters = vf_vlan_rules_cnt(vf); | 1166 | resc->num_vlan_filters = vf_vlan_rules_visible_cnt(vf); |
1167 | resc->num_mc_filters = 0; | 1167 | resc->num_mc_filters = 0; |
1168 | 1168 | ||
1169 | if (status == PFVF_STATUS_SUCCESS) { | 1169 | if (status == PFVF_STATUS_SUCCESS) { |